用于以下输入字符串,模式和:
$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 ) )
正如你所看到的阵列[2]给了Aditya Parikh,我希望也接受Vinton Heuck和Ciro Nieli。但没有。
任何解决方案??
答案 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 one。 Regular 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
)