正则表达式中的问号未按预期工作

时间:2016-09-23 11:56:17

标签: regex

我希望匹配>后的所有文字,并可选择匹配同一行上的链接:

preg_match('#(href="([^"]*))?.*>(.*)#', '<a href="world.html">Hello', $m);
print_r($m);

输入示例:

<a href="#catch-me" style="nice">Capture this text
This text should be ignored <a href="#me-too">Other text to capture
<p>This line has no link, but should be matched anyway.

预期结果:

[2] => world.html
[3] => Hello

实际结果:

[2] => 
[3] => Hello

如果我删除了问号,它会起作用,但是链接显然不再是可选的。

为什么会发生这种情况,我该如何解决?

1 个答案:

答案 0 :(得分:2)

在处理.*后面的可选子模式时,必须非常小心。

关键是,在可选模式之后的.*几乎总是&#34;采取&#34;可选的子模式值。你的正则表达式适用于像href="world.html">Hello这样的字符串。但如果它之前有其他符号则不行。

查看:当您try your regex<a href="world.html">Hello时,可以匹配空字符串的(href="([^"]*))? (遇到非匹配符号时不会失败) ,匹配开头<之前的位置。然后,.*发挥作用并匹配所有直到结束,并开始回溯。因此,表达式找到最后一个>,然后(.*)将该行的其余部分捕获到第3组。

因此,您可以将您的值与(href="([^"]*))?(?:(?!href=")[^>])*>(.*) tempered greedy token(与(?:(?!href=")[^>])*序列不匹配)的beforeunload documentation正则表达式匹配,或者将任务拆分为2个操作(是的,最好是):

1)抓住所有链接
 2)检查可选值。