首页 > 解决方案 > 为什么转义字符和正则表达式不能很好地与 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

似乎正则表达式中的\s字符集和+特殊字符不适用于 sed 命令。并且\n不被识别为新行。谁能告诉我原因或提供一些线索。谢谢你。

标签: bashmacossed

解决方案


sed 匹配基本正则表达式,而元字符+来自扩展正则表达式。\sPOSIX 字符类的简写[[:space:]]只能在某些 sed(例如 GNU sed)中作为扩展使用。同样\n,仅在某些 sed 中用作“换行符”,而在任何 sed 中,您都可以使用反斜杠后跟文字换行符。您在脚本周围使用双"引号 ( ) 而不是单引号 ( ') 会将其暴露给 shell,因此需要额外的反斜杠转义 - 始终在字符串或脚本周围使用单引号,除非您非常需要双引号(例如让一个变量扩展)并且只使用双精度,除非你有非常特殊的需要(例如,允许通配符扩展)。

在任何 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 将支持\s\n):

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

推荐阅读