为什么不使用sed命令转义字符和正则表达式?

时间:2019-04-05 04:10:52

标签: bash macos sed

在我的情况下,我想使用sed命令将一行与单词分开,如下所示,尽管我应该都可以使用。

[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/\s+/\n/g"
abc  def    gks       dps
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/\s\{1,\}/\n/g"
abc  def    gkn       dpn
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ \{1,\}/\n/g"
abcndefngksndps
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ \{1,\}/:/g"
abc:def:gks:dps
[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ +/:/g"
abc  def    gks       dps

但是实际上,只有一个有效。

[heping@Laputa:~]$echo "abc  def    gks       dps" | sed "s/ \{1,\}/:/g"
    abc:def:gks:dps

看来regex中的\s字符集和+特殊字符在sed命令中不能很好地工作。并且\n不被识别为新行。谁能告诉我原因或提供一些线索。谢谢。

2 个答案:

答案 0 :(得分:3)

sed与基本正则表达式匹配,而元字符+来自扩展正则表达式。 POSIX字符类\s的缩写[[:space:]]仅在某些sed(例如GNU sed)中作为扩展名有效。同样,\n在某些sed中仅充当“换行符”的含义,而在任何sed中,您都可以使用反斜杠后跟原义的换行符。您在脚本周围使用双引号("而不是单引号(')会将其暴露在外壳中,因此需要额外的反斜杠转义-除非在字符串或脚本中使用单引号,否则请始终使用单引号十分明确地需要双引号(例如,让变量扩展),并且仅使用双引号,除非您非常不需要双引号(例如,允许通配符扩展)。

要在任何POSIX sed中执行的操作是:

$ echo 'abc  def    gks       dps' | sed 's/[[:space:]][[:space:]]*/\
/g'
abc
def
gks
dps

,但这将与GNU sed一起使用(请注意-E+启用ERE-GNU sed和OSX / BSD sed支持,但是在这2个sed中,只有GNU sed支持{ {1}}和\s):

\n

答案 1 :(得分:1)

有几个问题。首先,sed默认使用基本正则表达式,但不能识别+。将-E修饰符用于扩展正则表达式。

第二,sed无法识别\n;但是您可以使用ANSI C quoting来使bash理解它。但是,如果仅使用\n,则sed模式中只会有一个换行符,因此必须避免换行符才能使sed实际使用;因此您需要\\进行转义,而\n进行换行,总共需要三个反斜杠。

最后,\s也不能被普通sed识别为字符类(但是在Linux发行版使用的GNU sed上可用)。如果您需要与(例如)相容,请改用文字空间。 OSX(或brew install gnu-sed)。

echo "abc  def    gks       dps" | sed -E $'s/ +/\\\n/g'
# => abc
#    def
#    gks
#    dps