在“任何地方”都能正常工作的正则表达式Regular expressions that work “everywhere”
正则表达式最令人沮丧的问题在于不同工具和语言之间的实现差异,特定功能可能完全缺失或语法略有不同。作者指出,在像 Perl 这样的最大化正则环境中学习的人,往往会在迁移到其他受限环境时感到受挫。为了解决这一痛点,文章探讨了如何编写具有广泛兼容性的正则表达式。这为需要在不同系统或工具间复用正则的开发者提供了实用的参考方案。
John
正则表达式最令人沮丧的一点在于其实现方式各不相同。在某个工具中受支持的功能,在另一个工具中可能完全不被支持,或者虽然支持,但语法上存在细微差异。
我是在 Perl 环境下学习正则表达式的,这是一个大而全的正则环境。这导致当我发现原本期望能用的功能缺失时,会感到十分沮丧 [1]。解决这个问题的方法之一是使用其他工具中类似 Perl 的等价功能,但这非常不标准。我希望能发给同事和客户可以直接开箱即用的代码。
正如我在关于“计算生存主义”的文章中所提到的,我偶尔需要在无法安装软件的电脑上工作。因此,更好的方法是找出一个能在任何地方通用的正则表达式功能子集。你对“任何地方”的定义越严格,这个子集包含的内容就越少。最严格的子集将是:
对“任何地方”更宽松一点的定义,就是你最关心的那些工具。目前,我最希望能配合正则表达式使用的工具是 sed、awk、grep 和 Emacs。
以 Awk 作为最小公分母
如果你使用 GNU 版本的 sed、awk 和 grep,并在 sed 和 grep 中使用 -E 选项,那么通用功能的列表会更长。这三个工具的正则表达式功能十分相似,并且 awk 的功能在其他工具中也受支持,但有一个例外:awk 中的单词边界是 \< 和 \>,而不是 \b 和 \B。
我曾在这里写过关于 Awk 正则表达式特性的文章。
特立独行的 Emacs
Emacs 支持大多数 awk 正则表达式功能的等价形式。然而,这些字符
+ ? ( ) { } |都需要在前面加上反斜杠,才能实现与 awk 中对应功能相同的效果。此外,awk 中 \s 和 \S 的等价形式在 Emacs 中是 \s- 和 \S-。
在 Emacs 中,\s 和 \S 并不表示空格或非空格,而是开启一个(反向)字符类,其中表示空格的类是 -。但还有很多其他的类。例如,\s. 代表标点字符,而 \S. 代表非标点字符。
处处通用的功能
因此,按照我对“任何地方”的定义,加上前面提到的注意事项,以下功能可以在任何地方通用。具体情况可能因人而异(YMMV)。
.
^, $
[…], [^…]
*
\w, \W, \s, \S
\1 - \9 backreferences
\b \B
? +
| alternation
{n,m} for counting matches
(...) capturing需要补充说明的是,gawk 支持在替换字符串中使用反向引用,但在正则表达式本身中并不支持。
[1] 在某种程度上,Perl 的基础功能可以在其他地方使用,而高级功能则不能,这取决于你对基础或高级的定义。我认为环视(look-around)功能是高级功能,事实也确实如此。但我认为代表数字的 \d 属于基础功能,然而许多正则表达式流派并不支持它。
需要完整排版与评论请前往来源站点阅读。