让我们考虑接下来的两个例子。
preg_match('/^(\pL+)(?:bcd|cd|d)$/u', 'abcd', $matches);
preg_match('/^(\pL+)(?:d|cd|bcd)$/u', 'abcd', $matches);
两个例子都返回' abc'为$matches[1]
。
为什么正则表达式不会在非匹配组中首先找到子模式?有可能停在' bcd'并得到一个'如$matches[1]
?
答案 0 :(得分:3)
要完成其他答案,这是对所发生情况的示意图:
str | pattern | state | description ------+----------------------+-----------+----------------------------------------- abcd | ^(\pL+)(?:bcd|cd|d)$ | SUCCESS | all letters are matched by \pL+ (greedy) abcd | ^(\pL+)(?:bcd|cd|d)$ | FAIL | there is no more character abcd | ^(\pL+)(?:bcd|cd|d)$ | FAIL | idem abcd | ^(\pL+)(?:bcd|cd|d)$ | FAIL | idem abcd | ^(\pL+)(?:bcd|cd|d)$ | BACKTRACK | \pL+ give one character back abcd | ^(\pL+)(?:bcd|cd|d)$ | FAIL | characters mismatch abcd | ^(\pL+)(?:bcd|cd|d)$ | FAIL | idem abcd | ^(\pL+)(?:bcd|cd|d)$ | SUCCESS | abcd | ^(\pL+)(?:bcd|cd|d)$ | SUCCESS |
最重要的是要理解,默认情况下量词是贪婪的并且可以使用所有字符。
注意:这是架构。在"现实生活"正则表达式引擎逐个字符地工作。在上面的示例中,当测试bcd
时,正则表达式引擎在失败之前显然只测试b
。
注意2:第二种模式不需要在回溯后测试bcd
和cd
。
答案 1 :(得分:2)
您可以使用:
preg_match('/^(\pL+?)(?>bcd|cd|d)$/u', 'abcd', $matches);
print_r($matches);
Array
(
[0] => abcd
[1] => a
)
答案 2 :(得分:1)
是的,通过使+
量词非贪婪:
preg_match('/^(\pL+?)(?:bcd|cd|d)$/u', 'abcd', $matches);
preg_match('/^(\pL+?)(?:d|cd|bcd)$/u', 'abcd', $matches);