对于 PCRE 正则表达式,[abc] 和 (a|b|c) 有什么区别?
3 回答
您问题中的模式匹配相同的文本。在实现方面,它们对应于不同的自动机和副作用(即它们是否捕获子字符串)。
在下面的评论中,加勒特奥尔布赖特指出了一个微妙的区别。而(.|\n)
匹配任何字符,[.\n]
匹配文字点或换行符。尽管点在字符类中不再是特殊的,但其他字符(例如-
, ^
, 以及]
诸如此类的序列)[:lower:]
在字符类中具有特殊含义。必须注意从一个上下文到另一个上下文保留特殊语义,但有时这是不可能的,例如在字符类之外的\1
一种古老的书写方式的情况下。$1
在字符类中,\1
始终匹配字符 SOH。
字符类 ( [...]
) 已针对匹配一组字符中的一个进行了优化,而替代 ( x|y
) 允许更一般的不同长度的选择。如果您牢记这些设计原则,您往往会看到更好的性能。正则表达式实现将源代码转换/[abc]/
为有限状态自动机,通常是NFA。我们认为的正则表达式引擎或多或少是协助执行这些目标状态机的簿记员。足够智能的正则表达式编译器将为等效的正则表达式生成相同的机器代码,但由于潜伏的指数复杂性,这在一般情况下既困难又昂贵。
有关正则表达式背后理论的易于理解的介绍,请阅读Mark Dominus 的“正则表达式如何工作”。如需更深入的研究,请考虑Peter Linz的《形式语言和自动机简介》 。
(在阅读格雷格的回答后):如果他们被不同的评估应该取决于你提供给他们的任何程序。选择您要检查的内容。您是要检查一组有效字符,还是要检查值。——有时看起来一样,但背后可能有不同的意图。然后选择反映您意图的内容。
使用方括号的形式在 PCRE 中要快得多,尤其是在启用 JIT 编译的情况下。它只是在 bitset 中检查一点,而另一个则为每个替代项重新读取字符。我正在考虑一种可以检测这种情况的优化,因为许多人不知道可以在方括号内使用字符类,并且他们使用 ([az]|\s)+ 而不是 [az\s]+。