sed命令与-i选项在Mac上失败,但在Linux上工作

我已经成功地使用下面的sed命令在Linux中search/replace文本:

 sed -i 's/old_link/new_link/g' * 

但是,当我在我的Mac OS X上尝试它时,我得到:

“命令c期望\后跟文本”

我以为我的Mac运行一个正常的BASH shell。 这是怎么回事?

编辑:

根据@High Performance的说法,这是由于Mac sed具有不同的(BSD)风格,所以我的问题是如何在BSD sed复制这个命令?

编辑:

这是一个实际的例子,导致这个:

 sed -i 's/hello/gbye/g' * 

如果使用-i选项,则需要为备份提供扩展名。

如果你有:

 File1.txt File2.cfg 

命令:

 sed -i '.original' 's/old_link/new_link/g' * 

创build2个备份文件,如:

 File1.txt.original File2.cfg.original 

没有可移植的方法来避免制作备份文件,因为不可能find适用于所有情况的sed命令组合:

  • sed -i -e ... – 在OS X上不起作用,因为它会创build-e备份
  • sed -i'' -e ... – 在OS X 10.6上不起作用,但在10.9+上工作
  • sed -i '' -e ... – 不能在GNU上工作

当您使用-i时,我相信OS X是需要备份文件的扩展名。 尝试:

 sed -i .bak 's/hello/gbye/g' * 

使用GNU sed扩展是可选的

这适用于sed的GNU和BSD版本:

 sed -i'' -e 's/old_link/new_link/g' * 

或备份:

 sed -i'.bak' -e 's/old_link/new_link/g' * 

请注意缺less-i选项后的空间! (GNU sed必备)

或者,您可以在Mac中安装sed的GNU版本(称为gsed),并使用标准的Linux语法来使用它。

为此,通过运行sudo port install gsed来安装使用端口(如果没有,请在http://www.macports.org/上获取)。; 然后,你可以运行sed -i 's/old_link/new_link/g' *

你的Mac确实运行了一个BASH shell,但是这更多的是你正在处理的sed实现的问题。 在Mac上,sed来自BSD,与典型的Linux机器上的sed有细微的差别。 我build议你的man sed

Sinetris的答案是正确的,但我用find命令来更具体地说明我想更改的文件。 一般来说,这应该工作(在osx /bin/bash上testing):

 find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \; 

一般情况下,在复杂项目中使用sed而不find效率较低。

在Mac中有相同的问题,并用brew解决:

 brew install gnu-sed 

并用作

 gsed SED_COMMAND 

你可以设置sed作为别名gsed (如果你想):

 alias sed=gsed 
 sed -ie 's/old_link/new_link/g' * 

适用于BSD和Linux

正如其他答案所指出的那样,没有办法在没有备份文件的情况下跨OS X和Linux使用sed。 所以,我使用这个ruby单线程来做到这一点:

 ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml 

在我的情况下,我需要从一个rake任务(即在一个Ruby脚本中)调用它,所以我使用了这个额外的引用级别:

 sh %q{ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml} 

以下是如何将环境variables应用于模板文件(无需备份)。

1.用{{FOO}}创build模板,以便以后replace。

 echo "Hello {{FOO}}" > foo.conf.tmpl 

2.用FOOvariablesreplace{{FOO}}并输出到新的foo.conf文件

 FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf 

同时使用macOS 10.12.4Ubuntu 14.04.5