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)
现在两个行/句子都将匹配.可悲的是,颜色不再匹配了.
问题是为什么?通过使用 ".*?" 在颜色部分之前,我以为我已经使正则表达式非贪婪,所以颜色部分会匹配,如果它存在的话.但正如所说,它不......
第一个(.*?)将匹配>和之间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)
作为旁注,我建议使用边界一词,这样你就不会像reduce或那样匹配jarred.