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

标签 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

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

为什么会发生这种情况以及如何解决它?

最佳答案

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

重点是.*在可选模式之后几乎总是“采用”可选子模式值。您的正则表达式适用于类似 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/

相关文章:

c++ - regex:找到数字和字符串交替的模式

java - 如何检查字符串是否包含小写字母、大写字母、特殊字符和数字?

regex - 跨多行替换两个单词之间的文件文本

PHP,验证用户提交的具有特定域的 URL

javascript - 如何使用 javascript 正则表达式检查 "empty"表单字段?

python - 如何正则表达式直到最后一次出现?

regex - 为什么 Groovy 正则表达式匹配器不能被否定?

javascript - 为什么即使正则表达式可以,但用正则表达式替换却不起作用?

python - 在 Python 中使用 RegEx 的函数解析器

c# - YYYYMMDD 日期格式正则表达式以在 C# .net 中验证日期