可在‘各处’工作的正则表达式
摘要
本文讨论了正则表达式在sed、awk、grep和Emacs等工具之间移植的挑战,并提供了一组在这些环境中可靠工作的正则表达式子集。
暂无内容
查看缓存全文
缓存时间: 2026/06/28 01:52
# “处处工作”的正则表达式
来源:https://www.johndcook.com/blog/2026/06/23/regex-everywhere/
正则表达式最令人沮丧的一点是不同实现各有差异。一个工具支持的功能,在另一个工具中可能完全不支持,或者虽支持但语法略有不同。
我最初是在 Perl 的环境中学习正则表达式的,那是一个极致的正则表达式环境。这导致当我期望某些功能能用时,却发现它们缺失了 [1]。一种解决方法是使用 Perl 的模拟工具(https://www.johndcook.com/blog/2013/08/20/perl-as-a-better/)来替代其他工具,但这非常不标准。我希望能够向同事和客户发送开箱即用的代码。
正如我在关于计算生存主义(https://www.johndcook.com/blog/2019/10/09/computational-survivalist/)的文章中提到的,我偶尔需要在无法安装软件的计算机上工作。因此,更好的方法是找出一个“处处工作”的正则表达式功能子集。你对“处处”的定义越严格,包含的内容就越少。最严格的子集是:
- 字面量
- 字符类 `\[...\]`
- 特殊字符 `\. \* ^ $`
更宽松的“处处”定义,是指你最关心的那些工具。目前我最常使用正则表达式的工具是 sed、awk、grep 和 Emacs。
## 以 Awk 作为最小公分母
如果你使用的是 Gnu 版本的 sed、awk 和 grep,并且在 sed 和 grep 中使用 `-E` 选项,那么共同支持的功能就会更多。这三个工具的正则表达式功能类似,awk 的功能在其他两个工具中也都支持,但有一个例外:awk 中的单词边界使用 `\\<` 和 `\\>`,而不是 `\b` 和 `\B`。
我在这里(https://www.johndcook.com/blog/awk-regular-expressions/)写过关于 Awk 正则表达式功能的文章。
## Emacs 是异类
Emacs 支持大多数 awk 正则表达式功能的模拟。然而,字符
```
+ ? ( ) { } |
```
都需要在前面加上反斜杠,才能起到与 awk 中对应的作用。另外,awk 中的 `\\s` 和 `\\S` 在 Emacs 中对应的写法是 `\\s-` 和 `\\S-`。
在 Emacs 中,`\\s` 和 `\\S` 不是表示空格或非空格,而是开始一个(取反的)字符类,其中 `-` 表示空格。但还有很多其他字符类。例如,`\\s.` 表示标点字符,`\\S.` 表示非标点字符。
## 处处工作的功能
因此,根据我对“处处”的定义,并加上上述注意事项,以下功能是处处工作的。你的情况可能有所不同。
```
.
^, $
[...], [^...]
*
\w, \W, \s, \S
\1 - \9 反向引用
\b \B
? +
| 分支
{n,m} 用于计数匹配
(...) 捕获分组
```
一个脚注:gawk 在替换字符串中支持反向引用,但在正则表达式本身中不支持。
[1] 在某种程度上,Perl 的基本功能在其他地方也能用,而高级功能则不行,这取决于你对“基本”和“高级”的看法。我把前瞻/后顾(https://www.johndcook.com/blog/2014/05/01/look-behind-regex/)视为高级功能,这没问题。但我觉得 `\d` 表示数字是基本功能,然而在许多正则表达式方言中并不支持。
相似文章
Stack Overflow 上 262,715 个正则表达式问题尚未解答的谜团
作者分析了 Stack Overflow 上的 262,715 个问题,以找出正则表达式的常见痛点,并展示了其新的正则表达式引擎 RE# 如何借助补集和交集运算来解决这些问题。
Stack Overflow上262,715个正则表达式问题尚未解答的问题(第二部分)
深入探讨正则表达式解析HTML的局限性,灵感来源于Stack Overflow的著名回答,讨论了形式语言理论和工业级正则表达式引擎的能力。
推荐一下……理解 Emacs 的模式
文章解释了 Emacs 的架构模式,重点介绍了通用缓冲区数据模型和增量补全读取(ICR),并将其比作玫瑰的根与花瓣。文章强调了 Emacs 如何统一界面并通过 Elisp 实现可扩展性。
Regex Chess: 一个使用84,688个正则表达式的2层minimax国际象棋引擎
Nicholas Carlini 的项目使用84,688个正则表达式实现了一个2层minimax国际象棋引擎,这些表达式被顺序执行以走出合法的国际象棋走法。文章解释了一个能够解读指令的正则表达式计算机的设计。
ReSyn: 一种广义的递归正则表达式合成框架
ReSyn是一个广义的递归框架,用于从示例中合成正则表达式,旨在改进现有的合成技术。