匹配json字符串的正则表达式

在处理日志时, 发现文本里夹杂有json字符串, 希望能准确提取出来. 于是就有了下面这个正则表达式:

(?<json>(?:\{\s*"(?:\\"|[^"])+"\s*:\s*(?:(?P>json)|"(?:\\"|[^"])+"|[-+]?(0|[1-9]\d*)(?:\.[-+]?(0|[1-9]\d*))?(?:[eE][-+]?(0|[1-9]\d*))?|(?:true|false)|null)(?:\s*,\s*"(?:\\"|[^"])+"\s*:\s*(?:(?P>json)|"(?:\\"|[^"])+"|[-+]?(0|[1-9]\d*)(?:\.[-+]?(0|[1-9]\d*))?(?:[eE][-+]?(0|[1-9]\d*))?|(?:true|false)|null))*\s*\}|\[\s*(?:(?P>json)|"(?:\\"|[^"])+"|[-+]?(0|[1-9]\d*)(?:\.[-+]?(0|[1-9]\d*))?(?:[eE][-+]?(0|[1-9]\d*))?|(?:true|false)|null)(?:\s*,\s*(?:(?P>json)|"(?:\\"|[^"])+"|[-+]?(0|[1-9]\d*)(?:\.[-+]?(0|[1-9]\d*))?(?:[eE][-+]?(0|[1-9]\d*))?|(?:true|false)|null))*\s*\]))

匹配规则完全符合官网规范说明 http://www.json.org
生成正则时得益于两种思想: 分而治之和递归
以下是生成正则的代码和简单的测试.

<?php
function json_reg() {
    echo '<xmp>';

    //基础元素
    $r_int   = '-?\d+'; //整数: 100, -23
    $r_blank = '\s*'; //空白
    $r_obj_l = '\\{'.$r_blank; // {
    $r_obj_r = $r_blank.'\\}'; // }
    $r_arr_l = '\\['.$r_blank; // [
    $r_arr_r = $r_blank.'\\]'; // [
    $r_comma = $r_blank.','.$r_blank; //逗号
    $r_colon = $r_blank.':'.$r_blank; //冒号

    //基础数据类型
    $r_str   = '"(?:\\\\"|[^"])+"';  //双引号字符串
    $r_num   = "{$r_int}(?:\\.{$r_int})?(?:[eE]{$r_int})?"; //数字(整数,小数,科学计数): 100,-23; 12.12,-2.3; 2e9,1.2E-8
    $r_bool  = '(?:true|false)'; //bool值
    $r_null  = 'null'; //null

    //衍生类型
    $r_key = $r_str; //json中的key
    $r_val = "(?:(?P>json)|{$r_str}|{$r_num}|{$r_bool}|{$r_null})"; //json中val: 可能为 json对象,字符串,num, bool,null
    $r_kv  = "{$r_key}{$r_colon}{$r_val}"; //json中的一个kv结构

    $r_arr = "{$r_arr_l}{$r_val}(?:{$r_comma}{$r_val})*{$r_arr_r}"; //数组: 由val列表组成
    $r_obj = "{$r_obj_l}{$r_kv}(?:{$r_comma}{$r_kv})*{$r_obj_r}";   //对象: 有kv结构组成

    $reg = "/(?<json>(?:{$r_obj}|{$r_arr}))/is";  //数组或对象
    echo $reg, "\n"; //最终正则表达式

    //以下是测试

    $str = '
  {
      "_in\"dex" : "log_idx",
      "_type" : "test",
      "_id" : "1",
      "_version" : 1,
      "_shards" : {
         "total" : 2,
         "successful" : 1.3,
         "successful0" : -1.3,
         "successful2" : 1.3e-3,
         "successful4" : 1.3E3,
         "failed" : 0
      },
      "created" : true
   }';


    preg_match_all($reg, $str, $arr);
    print_r($arr);

}

//调用函数执行
json_reg();

猜你喜欢

转载自blog.csdn.net/tsxw24/article/details/53373433