php preg_match_all反向引用

时间:2012-10-22 08:14:34

标签: php html regex preg-match-all backreference

用于以下输入字符串,模式和:

$str1 = 'span class="outline">Iron Man butts heads with Nick Fury and Shield after HYDRA attacks a meeting of the United Nations.</span>
<span class="credit">
    Dir: <a href="/name/nm0381817/">Vinton Heuck</a>, <a href="/name/nm1367649/">Ciro Nieli</a>, <a href="/name/nm1367649/">Aditya Parikh</a>'

$pattern='/class=&quot;credit&quot;&gt;[\s]+?Dir:([,\s]+?&lt;a[\s]+?href=&quot;\/name\/nm\d{7}\/&quot;&gt;([\/\(\)-:@!%*#=_|?$&;.\w\s]+?)&lt;\/a&gt;)+/um';

preg_match_all($pattern,$str1,$dir);

print_r的输出如下:

Array ( [0] => Array ( [0] => class="credit"> Dir: <a href="/name/nm0381817/">Vinton Heuck</a>, <a href="/name/nm1367649/">Ciro Nieli</a>, <a href="/name/nm1367649/">Aditya Parikh</a> ) [1] => Array ( [0] => , <a href="/name/nm1367649/">Aditya Parikh</a> ) [2] => Array ( [0] => Aditya Parikh ) )

正如你所看到的阵列[2]给了Aditya Parikh,我希望也接受Vinton Heuck和Ciro Nieli。但没有。

任何解决方案??

2 个答案:

答案 0 :(得分:1)

preg_match_all返回的匹配数组背后的逻辑并不那么明显。

首先,不要使用正则表达式来解析html。随着说:

您获得的结果是$array[paren_num][match_num]

的形式

一个基本的例子: abc针对正则表达式运行/(.)/将返回以下匹配数组:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

    [1] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

)

索引0包含所有使用的数据。索引1表示它是第一个反向引用(我们只有1个括号)。其中的0-2索引对应于每个匹配。换句话说,表达式运行了3次,直到完成。

我希望这会有所帮助。

答案 1 :(得分:1)

您应该考虑使用DOM解析器。例如,this oneRegular expressions just cannot properly parse HTML.

但是,这就是为什么你的方法不能按预期工作的原因:

您对所有3个名称使用相同的捕获组。但是一个捕获组只有一个数字,所以你总是会得到最后捕获的东西(最右边的名字)。但即使您只匹配一个名称(任意远离span标记),您也会遇到不同的问题:

匹配不能重叠。由于您想要的所有三个匹配项至少包含class="credit"> Dir:和一些更常见的文本,因此您无法获得所有这些匹配项。你可以用一个lookbehind断言来解决这个问题(因为它不是匹配的一部分),但不幸的是PHP不允许可变长度的lookbehinds(这是必需的)。有一些解决方法可以解决这个问题,但最终你最好使用DOM解析器。

以下是使用我上面链接的解析器的基本示例:

require "simple_html_dom.php";

$html = str_get_html($str1);

$names = array();
foreach($html->find('span[class=credit] a') as $link)
    $names[] = $link->innertext;

print_r($names);

导致:

Array
(
    [0] => Vinton Heuck
    [1] => Ciro Nieli
    [2] => Aditya Parikh
)