Php 要在首次找到子模式时停止的正则表达式

Php 要在首次找到子模式时停止的正则表达式,php,regex,Php,Regex,让我们考虑下面两个例子 preg_match('/^(\pL+)(?:bcd|cd|d)$/u', 'abcd', $matches); preg_match('/^(\pL+)(?:d|cd|bcd)$/u', 'abcd', $matches); 两个示例都将“abc”作为$matches[1]返回 为什么regex不首先在不匹配的组中找到子模式?是否可以在“bcd”处停止并获取“a”,因为$matches[1]?您可以使用: preg_match('/^(\pL+?)(?>bcd|

让我们考虑下面两个例子

preg_match('/^(\pL+)(?:bcd|cd|d)$/u', 'abcd', $matches);
preg_match('/^(\pL+)(?:d|cd|bcd)$/u', 'abcd', $matches);
两个示例都将“abc”作为
$matches[1]
返回

为什么regex不首先在不匹配的组中找到子模式?是否可以在“bcd”处停止并获取“a”,因为
$matches[1]

您可以使用:

preg_match('/^(\pL+?)(?>bcd|cd|d)$/u', 'abcd', $matches);
print_r($matches);
输出:
是,通过使
+
量词非贪婪:

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

要完成其他答案,以下是发生情况的示意图说明:

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 | str |模式|状态|描述 ------+----------------------+-----------+----------------------------------------- abcd ^(\pL+)(:bcd | cd | d)$|成功|所有字母都与\pL+(贪婪)匹配 abcd^(\pL+)(:bcd | cd | d)$|失败|没有更多字符 abcd ^(\pL+)(:bcd | cd | d)$| FAIL | idem abcd ^(\pL+)(:bcd | cd | d)$| FAIL | idem abcd^(\pL+)(:bcd | cd | d)$|回溯| \pL+返回一个字符 abcd ^(\pL+)(:bcd | cd | d)$|失败|字符不匹配 abcd ^(\pL+)(:bcd | cd | d)$| FAIL | idem abcd ^(\pL+)(:bcd | cd | d)$|成功| abcd ^(\pL+)(:bcd | cd | d)$|成功| 要理解的最重要的一点是,量词在默认情况下是贪婪的,它可以使用所有字符

注意:这是一个模式。在“现实生活”中,正则表达式引擎逐个字符地工作。在上面的示例中,当测试
bcd
时,regex引擎显然只测试
b
,然后失败


注2:在回溯之后,第二个模式不必测试
bcd
cd

Regex默认情况下想要贪婪。想想看,你正在尝试匹配表达式。如果它能匹配一个字符,它就会匹配。假设字符串
aaaaaaaaaaa
上有
/a+a/
。当您可以匹配所有a时,为什么要匹配
aa
。可能是出于相同的原因
^(\pL+)(:d)$
返回
abc
中的$matches[1]。请尝试
^(\pL+(:bcd)$
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 |