哪个更好的非贪婪正则表达式或否定角色类?

时间:2016-12-21 18:14:00

标签: regex string regex-negation non-greedy

我需要匹配字符串@anything_here@中的@anything_here@dhhhd@shdjhjs@。所以我使用了以下正则表达式。

^@.*?@

^@[^@]*@

这两种方式都有效,但我想知道哪种方法更好。具有非贪婪重复的正则表达式或带有否定字符类的正则表达式?

2 个答案:

答案 0 :(得分:5)

很明显,^@[^@]*@选项要好得多。

否定的字符类是量化的贪婪,这意味着正则表达式引擎尽可能多地立即获取除@以外的0个或更多个字符。请参阅this regex demo并匹配:

enter image description here

当您使用延迟点匹配模式时,引擎匹配@,然后尝试匹配尾随@(跳过.*?)。它在索引1处找不到@,因此.*?a字符匹配。此.*?模式扩展的次数与@以外的字符一样多,直到第一个@

请参阅lazy dot matching based pattern demo here,以下是匹配的步骤:

enter image description here

答案 1 :(得分:4)

如果可能,通常应该优先使用否定字符类进行延迟匹配。

如果正则表达式成功,^@[^@]*@可以在一个步骤中匹配@之间的内容,而^@.*?@需要针对@之间的每个字符进行展开。

如果失败(对于没有结尾@的情况),大多数正则表达式引擎会应用一点魔法并在内部将[^@]*视为[^@]*+,因为@之间存在明显的切割边界{1}}和非@,因此它会匹配字符串的结尾,识别丢失的@而不是回溯,但会立即失败。 .*?将像往常一样扩展角色的角色。

在较大的上下文中使用时,[^@]*也永远不会扩展到结尾@的边界,而这对于延迟匹配来说非常有可能。例如。 ^@[^@]*a[^@]*@@bbbb@a@的情况下不会与^@.*?a.*?@匹配。

请注意,[^@]也会匹配换行符,而.则不会(在大多数正则表达式引擎中,除非在单行模式下使用)。你可以通过在换行中添加换行符来避免这种情况 - 如果不需要的话。