我遇到以下情况:
...
preg_match('/#(.+?):(.+?)#/im','partA#partB#partC:partD#partE#partF',$matches);
...
执行后$ match变为
Array
(
[0] => #partB#partC:partD#
[1] => partB#partC
[2] => partD
)
如果我使用非贪婪的通配符$matches[1]
,partC
成为?
是否正常?我错过了什么吗?
我设法通过使用'/#([^#]+?):([^#]+?)#/im'
作为模式来解决它,但是相关的解释将很好地清除云。
感谢。
答案 0 :(得分:1)
捕获组1正在寻找#
然后查找任何内容(不包括新行),直到第一个:
。所以partB#partC
是有道理的。
你的修饰语也没有做任何事情。您没有区分大小写的字母,并且您没有使用锚点。
您可以在此处查看正则表达式的处理方式,https://regex101.com/r/iS0lW9/1。
答案 1 :(得分:1)
当你考虑正则表达式背后的基础理论时,这是有道理的。
正则表达式是所谓的finite state automaton (FSA)。这意味着它本质上会从左到右一次处理你的字符串一个字符,偶尔会倒退#34;放弃"字符。在您的示例中,正则表达式会看到第一个#
,并注意到#
没有参与模式的任何其他部分,开始匹配下一个标记(.+?
,在你的情况下)。它会一直到结肠,然后匹配下一个标记(再次,.+?
)。由于它是从左到右,它会匹配第一个哈希,然后停止,因为它是懒惰的。
这实际上是一种常见的误解 - 量词的?
修饰符不是非贪婪的,它是 lazy 。它会匹配最小可能的字符串,从左到右。
要修复原始正则表达式,您可以像这样修改它:
/.+#(.+?):(.+?)#/im
这样做会在冒号前的最后一个哈希值之前使用贪婪匹配,强制第一个捕获组仅使用该哈希值和冒号之间的内容。同样,该组也不需要延迟修饰符,产生最终的正则表达式:
/.+#(.+):(.+?)#/im