Macos sed没有给我正确的替换操作来替换带有Mac的新线-GNU sed和BSD/OSX sed之间的差异

Macos sed没有给我正确的替换操作来替换带有Mac的新线-GNU sed和BSD/OSX sed之间的差异,macos,sed,gnu,bsd,Macos,Sed,Gnu,Bsd,我正在使用此引用: 我有一个文件“test1.txt”,其中包含一个字符串hello\n goodbye 我使用此命令搜索“\n”并将其替换为实际的新行字符: sed -i '' 's/\\n/\n/g' test1.txt 但结果是:hellongoodbye。 它只是将“\n”替换为“n”,而不是实际的新行。这与/t相同,它将留下一个“t”而不是一个选项卡 “”用于MAC中未定义的错误: 更新: 我已经尝试了@hek2mgl建议的两个命令: sed -i 's/\\n/\n/g' test

我正在使用此引用:

我有一个文件“test1.txt”,其中包含一个字符串hello\n goodbye

我使用此命令搜索“\n”并将其替换为实际的新行字符:

sed -i '' 's/\\n/\n/g' test1.txt
但结果是:hellongoodbye。 它只是将“\n”替换为“n”,而不是实际的新行。这与/t相同,它将留下一个“t”而不是一个选项卡

“”用于MAC中未定义的错误:

更新

我已经尝试了@hek2mgl建议的两个命令:

sed -i 's/\\n/\n/g' test.txt
# Or:
sed -i'' 's/\\n/\n/g' test.txt
虽然他们可能使用Linux,但使用MAC OS时,我遇到了以下错误:

sed: 1: "test1.txt": undefined label 'est1.txt'

不知道为什么我不能让它工作。提前感谢。

这可能看起来有点奇怪,但请尝试:

sed -i '' 's/\\n/\
/g' test1.txt
即,使用实际换行,而不是
\n

原因是您有一个奇怪的
sed
! 有关详细信息,请参阅mac sed手册:

在那里的
s
命令的描述中,它说:

A line can be split by substituting a newline character into it.  To specify
a newline character in the replacement string, precede it with a backslash.

另外,在
-i
选项的描述中,它指出扩展不是可选的,如果不需要扩展,则必须指定一个空参数。所以最后一切都有意义

对于BSD/macOS
sed
,要在
s
函数调用的替换字符串中使用换行符,必须使用
\
-转义实际换行符
-此处不支持转义序列
\n
(与调用的regex部分不同)

  • 或者:只需插入实际换行:

    sed -i '' 's/\\n/\
    /g' test1.txt
    
  • 或者:在换行符中使用拼接(
    $'\n'
    ;在
    bash
    ksh
    zsh
    中工作):

相比之下,GNU
sed
,确实能够识别替换字符串中的
\n
;请继续阅读,全面了解这两种实现之间的差异


GNU
sed
(Linux)和BSD/macOS
sed
macOS使用BSD版本的
sed
[1],这在许多方面与Linux发行版附带的GNU
sed
版本有所不同

它们的共同点是POSIX规定的功能:参见

最可移植的方法是仅使用POSIX功能,但是限制了功能

  • 值得注意的是,POSIX只指定了对基本正则表达式的支持,这有很多限制(例如,根本不支持
    |
    (替换),不直接支持
    +
    )以及不同的转义要求。
    • 警告:GNU
      sed
      (不含
      -r
      ),不支持
      \\\\\
      \+
      \?
      ,不符合POSIX标准;使用
      --posix
      禁用
      (见下文)
  • 仅使用POSIX功能
    • (两个版本):仅使用
      -n
      -e
      选项(注意,不要使用
      -e
      -r
      来启用对扩展正则表达式的支持)
    • GNU
      sed
      :添加选项
      --posix
      ,以确保仅使用posix的功能(您并不严格需要它,但如果没有它,您可能会无意中使用非posix功能而不注意;警告:
      --posix
      本身不符合posix)
    • 仅使用POSIX功能意味着更严格的格式要求(放弃GNU
      sed
      中提供的许多便利):
      • 通常不支持控制字符序列,如
        \n
        \t
      • 标签和分支命令(例如,
        b
        )后面必须有一个实际的换行符或通过单独的
        -e
        选项的延续符
      • 详情见下文
但是,这两个版本都实现了对POSIX标准的扩展:

  • 它们实现的扩展不同(GNU
    sed
    实现更多)
  • 即使是它们都实现的扩展在语法上也有部分不同
如果您需要支持两种平台(讨论差异):

  • 不兼容的功能:
    • 使用不带参数的
      -i
      选项(不带备份的就地更新)是不兼容的:
      • BSD
        sed
        :必须使用
        -i'
      • GNU
        sed
        :必须只使用
        -i
        (等效:
        -i'
        )-使用
        -i'
        不起作用
    • -i
      在GNU
      sed
      和最新版本的BSD
      sed
      (例如,在FreeBSD 10上)中明智地打开每个输入文件行编号,但在10.15以后的macOS上不打开
      请注意,在没有
      -i
      的情况下,所有版本都会在输入文件中累积编号行
    • 如果最后一个输入行没有尾随换行符(并且已打印):
      • BSD
        sed
        :始终在输出端追加换行符,即使输入行未以换行符结尾
      • GNU
        sed
        :保留尾随换行符状态,即仅当输入行以一个换行符结尾时,它才会追加一个换行符
  • 常见功能:
    • 如果您将
      sed
      脚本限制在BSD
      sed
      支持的范围内,那么它们通常也会在GNU
      sed
      中工作-除了在
      -E
      中使用特定于平台的扩展正则表达式功能之外。显然,您还将放弃特定于GNU版本的扩展。见下一节

由更严格的
sed -i '' 's/\\n/\'$'\n''/g' test1.txt