正则表达式不选择中间组

Regular expression does not pick up middle group

(PHP)正则表达式为:

"/\b(screen|front|glass|lcd)\b.*?\b(not)?\b.*?\b(replaced|cracked|broken|chipped)\b/i"

目的是让正则表达式同时匹配:

"screen is not cracked"
"screen is cracked"

如果作为第二组出现,则选择 NOT。但是,对于上述示例输入,第二组似乎都是空的。

我做错了什么?

提示:我正在使用 http://www.regexe.com

进行测试

因为.*?匹配optional not的pattern之前也会贪婪匹配not。对于这种情况,您需要使用负前瞻。

(screen|front|glass|lcd)(?:(?!\bnot\b).)*(not)?.*?(replaced|cracked|broken|chipped)

(?:(?!\bnot\b).)* 将检查要匹配的字符是否是字符串 not 中的起始字母。如果是,那么它将匹配后面的字符。否则,它不会匹配以下字符,从而导致空匹配( 因为 *)。

DEMO

你忘记了"is"这个词

m!\b(screen|front|glass|lcd)\b *is *\b(not\b)?(replaced|cracked|broken|chipped)\b!i

您可以将第一个非贪婪量词放在可选组中,单词 "not":

\b(screen|front|glass|lcd)\b(?:.*?\b(not)\b)?.*?\b(replaced|cracked|broken|chipped)\b

因此 \b(not)\b 在非捕获组中不再是可选的,非贪婪量词开始工作并在达到 "not" 后停止。

一种优化的方式,懒惰地抓取单词直到 cracked/chipped/replaced/broken 并最终捕获 "not":

\b(screen|front|glass|lcd)\W+(?>(?:(not)|\w+)\W+)*?(?=[crb])(c(?:racked|hipped)|replaced|broken)\b