你可以试试这个:
$subject = <<<'LOD'
/* <![CDATA[ */ new Zbozi.Common.Result(
{ id: 'itemRow-0', url: 'http://www.muzikant.cz/zbozi/allen-heath-xone-22-81095.php', pos: '1' },
{ itemId: '3118517', longItemId: '117890214602569005', productId: '0', premiseId: '1675', zboziUserId: 'f11b5249-5e43-47f7-aca0-96ec4d0fde14',
sessionId: 'kQ8Fq1bSww4nr9E1kPBc', q: 'Allen & Heath Xone:22', title: 'ALLEN HEATH XONE:22', paid: 1, cn: '7770.00', frel: '948571',
crel: '0.952682', irel: '0.960918', x: 'pict' },
{ url: '/action/1675/clickthru?c=aaFoxUbWdnjpMksl5JN9avgl-1p673W9H8qxBpkl0O4xUptIPy0Y8P_IA72jS2Se_vxNj-eGQ5McH7EUlfXeeDVCYNIunim45PB8RS-eizcZorpKyMNlwTnUdUb1PjkvFQXDbSjMJeJmRcGnSWOyQyAGcL5ZQcreNFnXv1Xr5yEDjNxbPjyiD1mZI1Vm3PuqU7XrSrhtPx_LdipcNNdk2skaKYqFH-vRreCOwZ3F7ZWFbeOByzi3bg8eVJsFmyqNBy0uKaSdAF_yGMym4ZujVZPzvExObpsAMSHb0CtLK5KhNNYgTXP6bRKDAeJLGc-nnMdNKlOMuBKZKFaJrrWo6M60zsCM4tHvFGb30gb3s_M=',
label: 'item_featured', productName: 'ALLEN HEATH XONE:22', cp: '5B9DN0UD-qzuhuuvvKKZjg==' }, null ); /* ]]> */
LOD;
$replacements = array(
'~/\* \s*+ \Q<![CDATA[\E \s*+ \*/ \s*+ new \s++ \QZbozi.Common.Result\E \s*+ \( \s*+~x' => '[',
'~(?<=}) \s*+ , \s*+ null \s*+ \); \s*+ /\* \s*+ ]]> \s*+ \*/~x' => ']',
'~(?> \\{2} )*+ \K \'~x' => '"',
'~" [^"]*+ " (*SKIP) (*FAIL) | \s*+ (\w++) \s*+ : \s*+~x' => ' "$1":'
);
foreach ($replacements as $pattern => $replacement) {
$subject = preg_replace($pattern, $replacement, $subject);
}
var_dump($subject);
图案细节:
前两种模式旨在修剪(未来)JSON 对象前后不需要的内容。最后两个模式用于引号。
在所有模式中:
为了提高可读性,我使用了x
修饰符(扩展 mod),因此忽略了空格。同样,\Q.....\E
语法用于编写文字子串。(内部忽略特殊字符)。
所有量词都是所有格(++
或*+
)而不是简单的量词(+
或*
)。获得结果不是必需的(除了在第三种模式中),但那些向正则表达式引擎表明不需要记录回溯位置。您可以在此处找到更多相关信息。替换非捕获基团
的原子团也是如此 (?>.....)
(?:.....)
第一种模式:
没什么特别的,必须转义文字 atserisk 并\Q...\E
使用语法并避免转义方括号和点。
第二种模式:
后视 用于检查之前是否有右(?<=})
大括号。(这只是一个检查,这意味着里面的子(?<=...)
模式不是匹配的一部分)。
第三种模式:
此模式将找到未转义的单引号。为此,您必须验证单引号前是否有偶数个反斜杠或没有反斜杠。实际上,\\\\'
是两个反斜杠和一个引号,\\\\\'
是两个反斜杠和一个转义引号(即文字引号)。
\K
将从匹配结果中删除模式的开头(反斜杠检查)。只剩下单引号。
第四种模式:
这将找到所有后跟冒号的不在双引号内的单词(如http:
)。
您必须先找到双引号内的所有内容,"[^"]*+"
然后才能将其从匹配结果中排除。
要做到这一点,你不能使用这个\K
技巧,因为你是一个交替的一部分:.......\K|.......
。(如果第一部分成功,该preg_replace()
函数将在双引号内的每个子字符串之后添加替换模式!)
唯一的方法是正则表达式引擎在双引号中处理这些内容并失败。要做到这一点,您可以使用这两个回溯控制动词:(*SKIP)
和(*FAIL)
(*SKIP)
向正则表达式引擎指示先例子模式将失败并且可以跳过。
(*FAIL)
迫使模式失败。
这样,您就避免了双引号内的所有内容。然后交替的另一部分将只找到双引号外带有冒号的单词。