使一个或零正则表达式运算符贪婪

net*_*net 6 php regex greedy non-greedy regex-greedy

我有两个句子作为输入.比方说,举个例子:

<span>I love my red car.</span>
<span>I love my car.</span>
Run Code Online (Sandbox Code Playgroud)

现在我想匹配span-tags内的每个textpart(如果有颜色).

如果我使用以下正则表达式:

/<span>(.*?)(?P<color>red)(.*?)<\/span>/ms
Run Code Online (Sandbox Code Playgroud)

仅匹配具有颜色的线.所以我想让我们使用?-operator(一个或零).

/<span>(.*?)(?P<color>red)?(.*?)<\/span>/ms
Run Code Online (Sandbox Code Playgroud)

现在两个行/句子都将匹配.可悲的是,颜色不再匹配了.

问题是为什么?通过使用 ".*?" 在颜色部分之前,我以为我已经使正则表达式非贪婪,所以颜色部分会匹配,如果它存在的话.但正如所说,它不......

Jer*_*rry 5

第一个(.*?)将匹配>和之间I因为它是懒惰的,它会立即测试正则表达式的下一部分:(?P<color>red)?但是那时没有red,所以0选择?'激活'并且正则表达式继续到下一部分,即(.*?).它会再次匹配之间的部分>I和,因为它是懒惰的,它会检查正则表达式的下一部分:<\/span>(我把它作为一个整体).

所以第二个(.*?)将匹配到那里.

事实上,你的results[1]意志将是空的results[color](我不记得你是否必须引用color)并且results[3]将包含I love my red car..

嗯,一个解决方法是使用他在答案中提到的ORC.您可能使用的另一个方法是使用负前瞻来检查每个字符:

<span>((?:(?!\bred\b).)*(?<colour>\bred\b)?.*)<\/span>
Run Code Online (Sandbox Code Playgroud)

regex101演示

作为旁注,我建议使用边界一词,这样你就不会像reduce或那样匹配jarred.