在Mac上遇到Sed正则表达式问题,但在Linux上运行良好。

20

这在Linux (Debian)上运行良好:

sed -e 's,^[ \t]*psd\(.*\)\;,,' 

在 Mac 上,我相信我需要使用 -E 标志,而不是 -e

sed -E 's,^[ \t]*psd\(.*\)\;,,'

但是正则表达式不匹配,因此无法删除我想要的行。有什么解决方法吗?示例输入:
apa
bepa
    psd(cepa);
depa psd(epa);
  psd(fepa gepa hepa);

针对该输入,预期输出为:
apa
bepa
depa psd(epa);

1
你的预期输出应该有几行空白。你不需要转义分号。 - Michael J. Barber
5个回答

15

-E标志意味着使用扩展正则表达式。您应该只使用-e,就像在Linux上一样。Mac OS X中的sed基于BSD sed,因此没有GNU扩展。

复制示例输入后:

[~ 507] pbpaste | sed -e 's,^[[:space:]]*psd\(.*\);,,'
apa
bepa

depa psd(epa);

2
-E 在 GNU sed 上也可以使用,它是一个未记录的选项,被添加以符合 POSIX 标准。 - NDM

9

或者您可以使用GNU版的sed,而不是Mac OSX提供的实现。

Mac port提供了一个端口给它sudo port install gsed。安装后,您可以使用gsed代替sed


10
对于使用 Homebrew 的用户,可以通过执行 brew install gnu-sed --default-names 安装 GNU 版本的 sed 工具。 - Anton Babenko
3
喜欢 @AntonBabenko 的人需要注意:最近的版本中已经不再支持 --default-names 选项。请使用 brew install gnu-sed --with-default-names 命令并重新打开终端。请注意,这样做不会改变原来的意思。 - Bilal Akil
2
Homebrew的--with-default-names选项已被弃用(官方公式中的所有选项也是如此)。但是你可以通过执行ln -s /usr/local/bin/gsed /usr/local/bin/sed来创建自己的别名。但就个人而言,我不会这样做。一些shell脚本可能依赖于内置的BSD sed的行为,因此你可能会因此遇到一些神秘的问题。 - Chris

8

'\t'在标准的'sed'中并不是标准语法,它是GNU扩展的一部分。

要匹配一个'tab',你需要在脚本中插入一个真正的'tab'。这在文件中很容易实现,在shell中比较困难。

AIX、Solaris和HP-UX或其他UNIX系统中也可能会出现相同的问题。


6
我错过在我的回答中提到的内容。你可以随时使用POSIX字符类,[[:space:]][[:blank:]]都可以。要在shell中得到一个字面制表符,请按ctrl-v,然后键入制表符。 - Michael J. Barber

4
除了上面提供的答案之外,您还可以利用一个有用的(但依赖于Shell)技巧。在Bash中,使用$'\t'来引入一个字面制表符。以下命令在我的Mac上有效: sed -e 's,^[ '$'\t''*psd\(.*\);,,' 注意,整个sed表达式现在由三个连接的字符串组成。 这个技巧可能非常有用,因为它可以专门匹配制表符,而不会匹配其他空格(例如,当[[:blank:]]太宽泛时)。对于上述示例,-e标志并不是必需的。

2

我在我的电脑上检查了这个示例输入,并且在第三行开头有制表符时遇到了问题,正则表达式^[ \t]*psd\(.*\)\;没有匹配。可以通过使用sed字符类[[:blank:]]来解决,它等同于空格和制表符的组合。因此,您可以尝试以下内容:

sed -E 's,^[[:blank:]]*psd\(.*\)\;,,' demo.txt

这会产生以下输出:
apa
bepa

depa psd(epa);

但是它会保留结果中的空行。 为了得到您期望的精确输出,我使用了以下方法:
sed -n '/^[[:blank:]]*psd\(.*\)\;/!p' demo.txt

结果:

apa
bepa
depa psd(epa);

这只是匹配模式 (!p) 的反向输出。

编辑:在 sed (macosx) 中匹配制表符,您也可以尝试来自如何在 OS X 上使用 sed 插入制表符?的建议。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接