【问题标题】:PHP regex parse data between [ ]PHP正则表达式解析[]之间的数据
【发布时间】:2016-02-06 14:16:51
【问题描述】:

我有一个字符串,我想将其转换为有效的 JSON,然后对其进行 json_decode。 这是字符串的样子:

[
    ['test', 'lol'],
    ['test2', 'lol2']
]
[
    ['test32', 'loDl'],
    ['test32', 'loDl2']
]
[
    ['tes23t', 'loDEl'],
    ['testDE2', 'lolDE2']
]

我只想获取每个之间的数据

[

]

所以结果可能是:

['test', 'lol'],
['test2', 'lol2'],
['test32', 'loDl'],
['test32', 'loDl2'],
['tes23t', 'loDEl'],
['testDE2', 'lolDE2']

所以我认为我需要使用regexpreg_split,这就是我所做的:

$jsons = preg_split('/\]\s*(?=\[)/', $data, null);
$jsond = "";
foreach ($jsons as $json) {
     $json .= "";
     $jsond .= $json;
} 
return $jsond;

但它不起作用,我仍然无法获得每个 [ ] 之间的数据
我该怎么做?
提前致谢

PS:这是真正的完整字符串 https://paste.ee/r/RN7rK

【问题讨论】:

  • 不,不工作,我只得到很多\n
  • 由于您似乎有很多数据来自一个巨大的文件,我建议不要对整个内容使用全局正则表达式,而是使用流。
  • 好吧,为什么不试试\[([^\][]*)] 正则表达式,抓住$matches[1] 并随心所欲地使用它们?
  • 虽然您指向的链接是有效的 JSON,但您在问题中给出的示例不是。 JSON 将文本用双引号而不是单引号括起来。
  • @trincot 当我尝试验证我在链接中指向的 json 时,它使用 jsonlint.com 返回错误

标签: php json regex


【解决方案1】:

pointed to 的字符串在每一行都有有效的 JSON。但是,所有行加在一起并不代表一个有效的 JSON。

我建议以最小的方式操作数据,以使用简单的正则表达式制作整个文本 JSON。如果原始数据在 $data 中,则按如下方式创建 JSON:

$json = preg_replace('/(\])\](\R)\[/', '$1,$2', $data);

这将删除一行末尾的右括号和下一行开头的左括号。而是插入一个逗号。结果将是有效的 JSON,因为开头的左括号现在与最后的右括号匹配。

我从您的数据中提取了一些具有代表性的文本:

$data = '[["s","13","shelves_norja","49500","0","1","1","#ffffff,#F7EBBC","Beige Bookcase","For nic naks and books.","","5","true","-1","false","","1","true","0","0","0","false"],["s","117","table_plasto_round*9","45508","0","2","2","#ffffff,#533e10","Round Dining Table","Hip plastic furniture","","-1","false","-1","false","","1","false","0","0","0","false"]]
[["s","118","table_plasto_square*9","45508","0","1","1","#ffffff,#533e10","Occasional Table","Hip plastic furniture","","-1","false","-1","false","","1","false","0","0","0","false"],["s","119","chair_plasto*9","45508","0","1","1","#ffffff,#533e10,#ffffff,#533e10","Chair","Hip plastic furniture","","-1","false","-1","false","","1","false","0","1","0","false"],["s","120","carpet_standard*6","48082","0","3","5","#777777","Floor Rug","Available in a variety of colors","","105","true","-1","false","","1","true","1","0","0","false"],["s","121","chair_plasty*1","45508","0","1","1","#ffffff,#8EB5D1,#ffffff,#8EB5D1","Plastic Pod Chair","Hip plastic furniture","","-1","false","-1","false","","1","false","0","1","0","false"]]';

它只有两行,稍微限制数据。现在上面的代码产生了这个结果,打印得很漂亮:

[
    [
        "s",
        "13",
        "shelves_norja",
        "49500",
        "0",
        "1",
        "1",
        "#ffffff,#F7EBBC",
        "Beige Bookcase",
        "For nic naks and books.",
        "",
        "5",
        "true",
        "-1",
        "false",
        "",
        "1",
        "true",
        "0",
        "0",
        "0",
        "false"
    ],
    [
        "s",
        "117",
        "table_plasto_round*9",
        "45508",
        "0",
        "2",
        "2",
        "#ffffff,#533e10",
        "Round Dining Table",
        "Hip plastic furniture",
        "",
        "-1",
        "false",
        "-1",
        "false",
        "",
        "1",
        "false",
        "0",
        "0",
        "0",
        "false"
    ],
    [
        "s",
        "118",
        "table_plasto_square*9",
        "45508",
        "0",
        "1",
        "1",
        "#ffffff,#533e10",
        "Occasional Table",
        "Hip plastic furniture",
        "",
        "-1",
        "false",
        "-1",
        "false",
        "",
        "1",
        "false",
        "0",
        "0",
        "0",
        "false"
    ],
    [
        "s",
        "119",
        "chair_plasto*9",
        "45508",
        "0",
        "1",
        "1",
        "#ffffff,#533e10,#ffffff,#533e10",
        "Chair",
        "Hip plastic furniture",
        "",
        "-1",
        "false",
        "-1",
        "false",
        "",
        "1",
        "false",
        "0",
        "1",
        "0",
        "false"
    ],
    [
        "s",
        "120",
        "carpet_standard*6",
        "48082",
        "0",
        "3",
        "5",
        "#777777",
        "Floor Rug",
        "Available in a variety of colors",
        "",
        "105",
        "true",
        "-1",
        "false",
        "",
        "1",
        "true",
        "1",
        "0",
        "0",
        "false"
    ],
    [
        "s",
        "121",
        "chair_plasty*1",
        "45508",
        "0",
        "1",
        "1",
        "#ffffff,#8EB5D1,#ffffff,#8EB5D1",
        "Plastic Pod Chair",
        "Hip plastic furniture",
        "",
        "-1",
        "false",
        "-1",
        "false",
        "",
        "1",
        "false",
        "0",
        "1",
        "0",
        "false"
    ]
]

【讨论】:

  • 不工作,call_user_func_array() 期望参数 2 是数组,给定 null
  • 我更新了我的答案。我发现原始文本的每一行都有有效的 JSON,但换行符也代表 JSON 字符串的结尾和新字符串的开头。我在答案中添加了代码以将其转换为一个大型 JSON。让我知道这对你有什么作用。
  • 不,不是这个,我需要为每个“数据”打开和关闭 []
  • 那么preg_replace的结果一定是你需要的。我更新了我的答案,包括该语句的输出。可以查一下吗?
  • 有效的答案,这就是我要找的,谢谢
【解决方案2】:

如果你有很多数据并且必须保留内存,你可以使用这样的东西:

function genArrayFromFHandler($fh) {
    $state = 0; // (1: main brackets, 2: nested brackets, 3: quotes)
    while(!feof($fh)) {
        $c = fgetc($fh);

        switch($c):
            case '[':
                if ($state) $array = [];
                $state++;
                break;

            case ']':
                if ($state == 2) yield $array;
                $state--;
                break;

            case '"':
                if ($state == 2) {
                    $state++;
                    $item = '';
                } else {
                    $state--;
                    $array[] = $item;
                }
                break;

            default:
                if ($state == 3) $item .= $c;                

        endswitch;
    }
}

try {
    $fh = fopen('yourfile.txt', 'r');// or die ('error opening file');
    if (!$fh) throw new Exception('File open failed.');

    foreach (genArrayFromFHandler($fh) as $arr) {
        // do all what you need with the array here
        print_r($arr);
    }

    fclose($fh);

} catch (Exception $e) {
    echo $e->getMessage() . PHP_EOL;
}

这不是一个快速的方法,但内存占用非常低,因为文件永远不会完全加载到内存中。

注意我不知道你想对你的数据做什么,如果将它们转换为 JSON 是一个好主意(JSON 对于在应用程序之间共享数据很有用,但如果你想要一些你可以轻松有效地查询的东西,它是最好使用数据库。)

【讨论】:

  • 我用 curl 获取数据,所以我有一个错误“exepted to be ressource, string given”
  • @Mrz:如果是简单的url,把它作为fopen的第一个参数(而不是yourfile.txt)。您还可以使用stream_context_create 设置选项。
  • 我用 curl 得到了这个,因为网站阻止了 PHP 用户代理
  • @MrZ:你可以用stream_context_create覆盖用户代理并发送另一个。
【解决方案3】:

这也是可能的解决方案:

$data = preg_replace('/\s+/', '', $data);
$data = str_replace("[[", "[", $data);
$jsons = str_replace("]]", "]", $data);

回声 $jsons

['test','lol'],['test2','lol2']['test32','loDl'],['test32','loDl2']['tes23t','loDEl'],['testDE2','lolDE2']

【讨论】:

  • 得到一个错误 为 foreach() 提供的参数无效
【解决方案4】:
<?php

  $data = "[
      ['test', 'lol'],
      ['test2', 'lol2']
  ]
  [
      ['test32', 'loDl'],
      ['test32', 'loDl2']
  ]
  [
      ['tes23t', 'loDEl'],
      ['testDE2', 'lolDE2']
  ]";

  $matches = array();
  preg_match_all('/\[(.*?)\]/', $data, $matches);
  $json = '';

  foreach ($matches[0] as &$val) 
  {
      $json .= $val.',';
  } 

  $json = substr($json, 0, strlen($json)-1);

?>

将输出:

['test', 'lol'],['test2', 'lol2'],['test32', 'loDl'],['test32', 'loDl2'],['tes23t', 'loDEl'],['testDE2', 'lolDE2']

这是你想要的吗?

【讨论】:

  • 工作但斜线被转义并且 json_unescaped_slashes 不工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 2016-09-24
  • 2011-06-03
  • 2012-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多