准备正则表达式以使用格式良好的代码

时间:2013-10-25 22:00:05

标签: php regex

我正在研究从zbozi.cz获取数据的数据解析器,我遇到了问题。 函数解析正在准备从zbozi.cz获得的数据到有效的JSON并解码它。查看https://github.com/Northys/Venom/blob/master/libs/Venom/Strings.php

我对正则表达式并不熟悉,但我试图用我的书创建一个 - 我有这样的东西(我把它缩短了):

/* <![CDATA[ */ new Zbozi.Common.Result( { id: 'itemRow-0', ... }, { itemId: '3118517',...}, { url: ... }, null ); /* ]]> */

我需要获得一个有效的JSON来解析它与我的解析函数。我正在使用模式/.*\( /preg_replace函数在{ id:...}出现之前删除内容。不幸的是,将来他们可以添加更多的空格,整理代码或使我的脚本不起作用的东西。

我需要的一切就是编辑解析功能(链接下面的链接)。对于str_replace函数,需要更改第23行上的正则表达式模式和以下行中的某些preg_replace。你能帮我吗?

这是我的脚本使用的代码 - https://github.com/Northys/Venom/blob/master/crawled/1.html - 只需点击CTRL F并找到 Zbozi.Common.Result

我的脚本无效 https://github.com/Northys/Venom/blob/master/crawled/0.html - 第305行

我需要更改正则表达式以使其适用于这两个文件。

1 个答案:

答案 0 :(得分:1)

你可以试试这个:

$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 &amp; 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);

模式细节:

这两个第一个模式旨在修剪(futur)JSON对象之后和之前不需要的内容。最后两种模式用于引用。

所有模式:

为了更具可读性,我使用x修饰符(扩展mod),因此忽略了空格。以同样的方式,\Q.....\E语法用于编写litteral子字符串。 (内部忽略特殊字符。)

所有量词都具有占有性(++*+),而非简单量词(+*)。获得结果并不是必需的(除了第三种模式),但那些表明正则表达式引擎不需要记录回溯位置。您可以找到有关此here的更多信息 替换非捕获组(?>.....)

atomic groups (?:.....)也是如此

第一种模式:

没有什么特别的,字面上的atserisk必须被转义并使用\Q...\E语法,并避免摆脱方括号和圆点。

第二种模式:

lookbehind (?<=})用于检查之前是否有结束花括号。 (这只是一个检查,这意味着(?<=...)内的子模式不是匹配的一部分)

第三种模式:

此模式将查找未转义的单引号。为此,您必须在单引号之前验证是否存在偶数个反斜杠或没有反斜杠。实际上,\\\\'是两个反斜杠和一个引号,\\\\\'是两个反斜杠和一个转义引号(即文字引号)。

\K将从匹配结果中删除模式的开头(反斜杠检查)。仍然只有单引号。

第四种模式:

这将找到所有不在双引号(如http:内的冒号后面的单词。

您必须先找到双引号"[^"]*+"内的所有内容才能将其从匹配结果中排除。
为此,您无法使用\K技巧,因为您是交替的一部分:.......\K|.......(如果第一部分成功,preg_replace()函数将在双引号内的每个子字符串后添加替换模式!
唯一的方法是正则表达式引擎以双引号继续这些内容并失败。要做到这一点,您可以使用这两个backtrack control verbs(*SKIP)(*FAIL)
(*SKIP)向正则表达式引擎指示先前的子模式将失败并且可以跳过 (*FAIL)迫使模式失败。

这样你就避免了双引号内的所有内容。然后,交替的另一部分将只找到带双引号外的冒号的单词。