正则表达式在第一次找到子模式时停止

时间:2014-03-11 15:33:38

标签: php regex

让我们考虑接下来的两个例子。

preg_match('/^(\pL+)(?:bcd|cd|d)$/u', 'abcd', $matches);
preg_match('/^(\pL+)(?:d|cd|bcd)$/u', 'abcd', $matches);

两个例子都返回' abc'为$matches[1]

为什么正则表达式不会在非匹配组中首先找到子模式?有可能停在' bcd'并得到一个'如$matches[1]

3 个答案:

答案 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:第二种模式不需要在回溯后测试bcdcd

答案 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);