返回

sed 命令中 \d 不起作用?BRE 和 ERE 正则表达式的区别

Linux

很多人刚接触 sed 命令,特别是想用它来处理文本的时候,经常会碰到一个奇怪的问题:\d 不起作用!明明在 Python、Java 或者 JavaScript 里面,\d 都能匹配数字,怎么到了 sed 这里就失效了呢?别着急,这其实跟 sed 使用的正则表达式引擎有关。

sed 默认情况下使用的是 基础正则表达式 (BRE) 。BRE 是一种比较古老的正则表达式规范,功能相对简单。在 BRE 中,像 \d\w\s 这种表示数字、字母或空白字符的简写方式是不被支持的。如果你想在 sed 中使用这些简写,就需要切换到 扩展正则表达式 (ERE) 模式。

那怎么才能让 sed 使用 ERE 呢?方法很简单,主要有两种:

  1. 使用 -r-E 选项
    sed 命令后面加上 -r 或者 -E 选项,就能告诉 sed 使用 ERE 引擎来处理正则表达式了。比如:

    sed -r 's/\d+//g' file.txt
    sed -E 's/\d+//g' file.txt
    

    这两条命令的效果是一样的,都会把 file.txt 文件中所有的数字都删掉。

  2. 使用反斜杠转义
    如果你不想使用 -r-E 选项,也可以在正则表达式中使用反斜杠 \ 来转义 \d,让 sed 把它识别成特殊的字符类,而不是普通的字符 'd'。例如:

    sed 's/\\d+//g' file.txt
    

    这条命令也能达到同样的效果,只不过写起来稍微麻烦一点。

明白了 BRE 和 ERE 的区别,我们就能理解为什么 sed -r 's/\d+//g' 可以正常工作,而 sed 's/\d+//g' 却不行了。前者使用了 -r 选项开启了 ERE 模式,而后者仍然在使用 BRE 模式,当然无法识别 \d 了。

不过,即使你使用了 ERE 模式,也并非所有版本的 sed 都支持 \d 等简写字符类。有些比较老的 sed 版本可能仍然不支持这些特性。如果你遇到了这种情况,可以用 [0-9] 来代替 \d,例如:

sed -r 's/[0-9]+//g' file.txt

这种写法在 BRE 和 ERE 模式下都能正常工作,兼容性更好,不用担心 sed 版本的问题。

除了 \d 之外,还有其他一些简写字符类也需要注意:

简写字符类 含义 等价的字符集
\d 匹配数字 [0-9]
\w 匹配字母、数字、下划线 [a-zA-Z0-9_]
\s 匹配空白字符 [ \t\r\n\f]
\D 匹配非数字 [^0-9]
\W 匹配非字母、数字、下划线 [^a-zA-Z0-9_]
\S 匹配非空白字符 [^ \t\r\n\f]

这些简写字符类在 ERE 模式下都能直接使用,但在 BRE 模式下需要使用反斜杠转义或者使用等价的字符集来表示。

总之,\dsed 中不起作用的主要原因是 sed 默认使用 BRE 模式,而 BRE 不支持 \d 这种简写字符类。我们可以通过开启 ERE 模式或者使用反斜杠转义来解决这个问题。为了更好的兼容性,也可以直接使用 [0-9] 来代替 \d

希望这篇文章能帮助你更好地理解 sed 中正则表达式的使用,避免在实际操作中遇到类似的问题。

常见问题解答

1. sed -rsed -E 有什么区别?

答:sed -rsed -E 的作用完全相同,都是用来开启 ERE 模式的。只是不同的操作系统可能更倾向于使用其中一种选项,比如 macOS 和 FreeBSD 更常用 -E,而 GNU/Linux 更常用 -r

2. BRE 和 ERE 还有什么区别?

答:除了是否支持简写字符类之外,BRE 和 ERE 在一些元字符的用法上也有一些区别。比如,在 BRE 中,+?|() 等元字符需要使用反斜杠转义才能表示它们的特殊含义,而在 ERE 中则可以直接使用。

3. sed 中的正则表达式跟其他编程语言的正则表达式一样吗?

答:大体上是类似的,但 sed 的正则表达式有一些自己的特点,比如它不支持捕获组和非贪婪匹配。如果你想在 sed 中使用更高级的正则表达式特性,可以考虑使用 perlawk 等工具。

4. sed 命令太复杂了,有没有更简单的工具可以用来处理文本?

答:当然有!如果你只是想做一些简单的文本替换或者提取操作,可以使用 grepawk 或者 cut 等命令,它们比 sed 更容易上手。

5. 在哪里可以学习更多关于 sed 和正则表达式的知识?

答:网上有很多关于 sed 和正则表达式的教程和文档,你可以在搜索引擎中搜索 "sed tutorial" 或者 "regular expression tutorial" 来找到它们。此外,sedgrep 等命令都有自己的 man 手册,你可以在终端中输入 man sed 或者 man grep 来查看它们的使用方法和详细说明。