我需要匹配字符串@anything_here@
中的@anything_here@dhhhd@shdjhjs@
。所以我使用了以下正则表达式。
^@.*?@
或
^@[^@]*@
这两种方式都有效,但我想知道哪种方法更好。具有非贪婪重复的正则表达式或带有否定字符类的正则表达式?
答案 0 :(得分:5)
很明显,^@[^@]*@
选项要好得多。
否定的字符类是量化的贪婪,这意味着正则表达式引擎尽可能多地立即获取除@
以外的0个或更多个字符。请参阅this regex demo并匹配:
当您使用延迟点匹配模式时,引擎匹配@
,然后尝试匹配尾随@
(跳过.*?
)。它在索引1处找不到@
,因此.*?
与a
字符匹配。此.*?
模式扩展的次数与@
以外的字符一样多,直到第一个@
。
请参阅lazy dot matching based pattern demo here,以下是匹配的步骤:
答案 1 :(得分:4)
如果可能,通常应该优先使用否定字符类进行延迟匹配。
如果正则表达式成功,^@[^@]*@
可以在一个步骤中匹配@
之间的内容,而^@.*?@
需要针对@
之间的每个字符进行展开。
如果失败(对于没有结尾@
的情况),大多数正则表达式引擎会应用一点魔法并在内部将[^@]*
视为[^@]*+
,因为@
之间存在明显的切割边界{1}}和非@
,因此它会匹配字符串的结尾,识别丢失的@
而不是回溯,但会立即失败。 .*?
将像往常一样扩展角色的角色。
在较大的上下文中使用时,[^@]*
也永远不会扩展到结尾@
的边界,而这对于延迟匹配来说非常有可能。例如。 ^@[^@]*a[^@]*@
在@bbbb@a@
的情况下不会与^@.*?a.*?@
匹配。
请注意,[^@]
也会匹配换行符,而.
则不会(在大多数正则表达式引擎中,除非在单行模式下使用)。你可以通过在换行中添加换行符来避免这种情况 - 如果不需要的话。