我想匹配 >
之后的所有文本,并可选择匹配同一行上的链接:
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
如果我删除问号,它就会起作用,但链接显然不再是可选的。
为什么会发生这种情况以及如何解决它?
最佳答案
处理 .*
后面的可选子模式时,必须非常小心。
重点是.*
在可选模式之后几乎总是“采用”可选子模式值。您的正则表达式适用于类似 href="world.html">Hello
的字符串。但如果它前面有其他符号则不然。
看:当你 try your regex反对<a href="world.html">Hello
,(href="([^"]*))?
可以匹配空字符串(遇到不匹配符号时不会失败),匹配 <
之前的位置一开始。然后,.*
开始比赛并匹配到最后,然后开始回溯。因此,该表达式找到最后一个 >
然后(.*)
将该行的其余部分捕获到第 3 组中。
因此,您可能可以将您的值与 (href="([^"]*))?(?:(?!href=")[^>])*>(.*)
相匹配。具有 (?:(?!href=")[^>])*
的正则表达式tempered greedy token (与 href="
序列不匹配),或将任务分成 2 个操作(是的,这是更好的选择):
1) 获取所有链接
2) 检查可选值。
关于regex - 正则表达式中的问号未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39660196/