简单的 sed 选项卡替换神秘地失败

简单的 sed 选项卡替换神秘地失败

这应该非常简单,但由于某种原因它不起作用:

sed -i.bak -E 's/\t/  /' file.txt

它不是替换制表符,而是替换t字符。我已经尝试了我能想到的所有变体,比如引用等等。我用谷歌搜索并发现其他所有人使用非常相似的表达方式,它们似乎对他们有用。

-E是 OS X 的事情。我认为失败可能是 OS X 的一些奇怪的怪癖造成的sed,所以我也用 Ruby 尝试了它(没有-i),并得到了相同的结果:

ruby -pe '$_.gsub!(/\t/,"  ")' < file.txt > file.new

我在 OS X 和 iTerm 上使用 Bash 3.2.51,尽管我看不出其中任何一个有什么关系。我没有设置任何奇怪的环境变量,尽管我可以发布您认为可能相关的任何变量。

可能出什么问题了?

更新:当我尝试 Ruby 版本时,我一定犯了一些其他错误或拼写错误,因为 Gilles 指出它工作(而且我已经绝不让他误导了我!)。我不确定发生了什么,但我很确定这一定是我的错误。

答案1

sed 中制表符的语法\t不是标准的。那个逃脱是一个GNU sed 扩展。您可以在网上找到很多使用它的示例,因为很多人使用 GNU sed(它是非嵌入式 Linux 上的 sed 实现)。但OS X sed与其他 *BSD sed 一样,不支持\t制表符,而是将其视为\t反斜杠后跟的含义t

解决方案有很多,例如:

  • 使用文字制表符。

    sed -i.bak 's/  /  /' file.txt
    
  • 使用trprintf产生制表符。

    sed -i.bak "s/$(printf '\t')/  /" file.txt
    sed -i.bak "s/$(echo a | tr 'a' '\t')/  /" file.txt
    
  • 使用 bash 的允许反斜杠转义的字符串语法

    sed -i.bak $'s/\t/  /' file.txt
    
  • 使用 Perl、Python 或 Ruby。您发布的 Ruby 代码片段确实有效。

答案2

使用 Bash 特定的引用它允许您像 C 中一样使用字符串,以便将真正的制表符传递给 sed,而不是转义序列:

sed -i.bak -E $'s/\t/  /' file.txt

答案3

sed -i $'s/\t/  /g' file.txt 

在 OS X 上适用于我,并且与我一直在 Linux 上使用的命令相同。

答案4

如果您想要比 OS X 上的更强大sed(支持\t等),请安装GNU sed

相关内容