[英]php 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="credit">[\s]+?Dir:([,\s]+?<a[\s]+?href="\/name\/nm\d{7}\/">([\/\(\)-:@!%*#=_|?$&;.\w\s]+?)<\/a>)+/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 ) )
你可以看到Array [2]给了Aditya Parikh,我也希望收到Vinton Heuck和Ciro Nieli。 但没有。
任何解决方案
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次,直到完成。
我希望这有帮助。
您应该考虑使用DOM解析器。 例如, 这一个 。 正则表达式无法正确解析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
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.