【发布时间】:2012-05-28 07:32:54
【问题描述】:
对于PCRE正则表达式,[abc]和(a|b|c)有什么区别?
【问题讨论】:
对于PCRE正则表达式,[abc]和(a|b|c)有什么区别?
【问题讨论】:
您问题中的模式匹配相同的文本。在实现方面,它们对应不同的自动机和副作用(即,是否捕获子字符串)。
在下面的评论中,Garrett Albright 指出了一个微妙的区别。 (.|\n) 匹配任何字符,[.\n] 匹配文字点或换行符。尽管点在字符类中不再特殊,但其他字符(例如 -、^ 和 ])以及诸如 [:lower:] 之类的序列在字符类中具有特殊含义。必须注意从一个上下文到另一个上下文保留特殊语义,但有时这是不可能的,例如 \1 作为在字符类之外编写 $1 的一种古老方式。在字符类中,\1 始终匹配字符 SOH。
字符类 ([...]) 已针对匹配一组字符中的一个进行了优化,而替代品 (x|y) 允许更通用的不同长度的选择。如果您牢记这些设计原则,您往往会看到更好的性能。正则表达式实现将源代码(例如/[abc]/)转换为有限状态自动机,通常是NFAs。我们认为的正则表达式引擎或多或少是协助执行这些目标状态机的簿记员。足够智能的正则表达式编译器将为等效的正则表达式生成相同的机器代码,但由于lurking exponential complexity,这在一般情况下既困难又昂贵。
有关正则表达式背后理论的易于理解的介绍,请阅读 Mark Dominus 的 “How Regexes Work”。如需更深入的研究,请考虑 Peter Linz 的 An Introduction to Formal Languages and Automata。
【讨论】:
\n 或\r。例如,要捕获 FOO 和 BAR 之间的所有文本,包括换行符,/FOO((.|\n)+)BAR/ 有效,而 /FOO([.\n]+)BAR/ 无效。不过,这可能是特定于实现的。我发现了其他类似的差异,我想不起来了。无论如何,作为一项规则,我会首先尝试使用[ab],因为它更具可读性,然后如果事情似乎不起作用,请尝试使用(a|b)。
(在阅读 Greg 的回答后):如果对它们进行不同的评估,应该取决于您提供给它们的任何程序。选择您要检查的内容。您是要检查一组有效字符,还是要检查值。 ——有时看起来一样,但背后可能有不同的意图。然后选择反映您意图的内容。
【讨论】:
使用方括号的形式在 PCRE 中要快得多,尤其是在启用 JIT 编译的情况下。它只是在位集中检查一点,而另一个则为每个替代项重新读取字符。我正在考虑一种可以检测这种情况的优化,因为许多人不知道可以在方括号内使用字符类,并且他们使用 ([az]|\s)+ 而不是 [az\s]+。
【讨论】: