2014-03-31 62 views
1
perl -ne 'print if /^(?=.*?\bPavel\b)(?=.*?\bDavid\b)((?!Petr|Jan)).*$/' 

输入:Honza,David,Pavel,Marie,AdamPerl - 为什么这个正则表达式匹配?

我认为它不应该通过,但它确实。

第一个先行应该'消耗'Honza,David,Pavel并且第二个先行应该失败,因为在Pavel之后没有David,或者?

+0

'*'是不贪婪?如果是'。*',那么它会是贪婪的 –

+0

如果这是你实际需要的行为,试试类似'\ bPavel(,\ b。* \ b)?, David \ b(?!Petr | Jan) ',可能实际上使用通配符'(?!。* \ b(Petr | Jan))',因为无论如何它们永远不可能与'David \ b'相邻。 – tripleee

+1

@MarcB:贪婪或非贪婪在预测中没有区别,因为它们是* zero-width *匹配。 – Borodin

回答

4

第一个预测应该'消耗'Honza,David,Pavel

完全没有。它被称为零宽度积极lookahead因为它不消耗任何东西。它不会推进下一个原子必须匹配的位置,所以它必须在零位处匹配。


(?!Petr|Jan)不会按原样工作。它只是检查它们是否在字符串的开头。你可以使用

/^(?=.*\bPavel\b)(?=.*\bDavid\b)(?!.*\b(?:Petr|Jan)\b)/x 

这基本上是

/\bPavel\b/ && /bDavid\b/ && !/\b(?:Petr|Jan)\b/ 

一个melding这种方法只适用,因为你正在寻找,直到字符串的结尾。

+0

@aa现在我明白了,ty – Krab

+0

注意ikegami已经移除了无用的'。* $',它永远不会影响它是否匹配 – ysth

3

独立lookaheads不“消费”任何东西。这相当于:

print if /^(?=.*?\bPavel\b)/ && /^(?=.*?\bDavid\b)/ && /^((?!Petr|Jan))/' 

可以只是简单:

perl -ne 'print if /\bPavel\b/ && /\bDavid\b/ && /^((?!Petr|Jan))/' 
相关问题