必须用PCRE递归模式/\[(?:[^\[\]]|(?R))*\]/s匹配最外层JSON数组,其中(?R)递归处理嵌套结构,s修饰符支持跨行匹配;提取后需trim()清洗并json_decode()验证,正则仅适用于非标准JSON的预提取场景。

用 preg_match 提取最外层 JSON 数组时,为什么总多匹配一层?
因为 /\[.*?\]/s 这类简单正则会停在第一个 ],而不管它是否属于嵌套结构。比如 [{"a": [{"b": 1}]}] 中,懒惰匹配会在内层 ] 就结束,结果是 [{"a": [{"b": 1} —— 不合法、无法 json_decode。
preg_match 如何正确匹配带嵌套的 JSON 数组?
必须用 PCRE 的递归模式,让正则能“数括号”:
-
/\[(?:[^\[\]]|(?R))*\]/s:匹配最外层[]及其所有嵌套内容;[^\[\]]跳过非括号字符,(?R)递归匹配自身,处理内部[...]或{...} - 若只提取数组(不包含对象),可微调为
/\[(?:[^[\]]|(?R))*\]/s,但实际中 JSON 允许数组里含对象,所以原递归式更稳妥 - 务必加
s修饰符,否则换行符会打断匹配
匹配后 json_decode 失败的常见原因
即使正则提取出完整字符串,json_decode 仍可能返回 null,原因包括:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 提取结果开头或结尾混入空格、分号、逗号等非 JSON 字符(如
[...];或var data = [...];)——需用trim($match, " \t\n\r;")清洗 - JSON 中含 PHP 风格注释(
//或/* */)——正则无法识别,json_decode直接拒解 - 字符串里有未转义的双引号或控制字符(如
"name": "A"lice")——这不是正则问题,而是源数据非法,json_last_error()会返回JSON_ERROR_SYNTAX
什么时候不该用正则?
正则只是“不得已的提取手段”,不是 JSON 解析器:
立即学习“PHP免费学习笔记(深入)”;
- 如果原始文本是标准 JSON(哪怕带多余空格),直接
json_decode($text)更安全可靠 - 若文本中存在多个 JSON 片段(如日志里穿插多个
{...}),preg_match_all可能漏掉或错位,此时应逐行扫描 + 状态机,而非依赖单条正则 - 遇到 Unicode 转义、长字符串、深层嵌套(>10 层),PCRE 递归可能栈溢出,
ini_set('pcre.recursion_limit', '2000')可缓解但治标不治本
真正难处理的是“伪 JSON”——比如 JS 模板字面量、PHP 数组语法、HTML 内联脚本。这时正则只是第一步,后续还得做语法转换,风险远高于直接修复上游输出格式。


















