带有-i选项的sed命令在Mac上失败,但在Linux上有效


303

我已成功使用以下sed命令在Linux中搜索/替换文本:

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' *

1
这意味着sed您会在命令中看到“ c”。您正在使用变量吗?请发布一些更能代表实际命令和正在处理的数据的内容。您可以通过执行来简单地演示此错误echo x | sed c
暂停,直到另行通知。

@Dennis,上面的简单命令会导致此问题,尽管它处理的数据是整个网站(我正在转换所有图像链接),包括html和css文件...
Yarin

Answers:


397

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

如果你有:

File1.txt
File2.cfg

该命令(注意缺乏之间的空间-i,并''-e以使其在Mac和在GNU新版本一起使用):

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

创建2个备份文件,例如:

File1.txt.original
File2.cfg.original

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

  • sed -i -e ...-创建-e备份时无法在OS X上使用
  • sed -i'' -e ... -不适用于OS X 10.6,但适用于10.9+
  • sed -i '' -e ... -不适用于GNU

注意鉴于在所有平台上都没有sed命令,您可以尝试使用另一个命令来获得相同的结果。

例如, perl -i -pe's/old_link/new_link/g' *


4
我遇到过同样的问题。感谢您的解决方案。但是,当我尝试使用'man sed'查找'-i'的描述时,却没有使用-i''忽略备份的内容。这是我的第一责备。其次,当出现错误“命令期望\后跟文本”时,为什么不直接告诉我们它期望选项'-i'的备份名称!这样的事情无处不在:您得到一个错误,而不是为什么出错,然后您搜索没有任何解释的手册。然后,您用谷歌搜索其他人也有同样的问题。我的意思是,为什么不在手册中举例说明?
lukmac

或告诉我们为什么会出现错误,而不是仅显示一条信息,指出发生错误。这是对所有工具制造商的建议,前提是他们可以阅读此评论。
lukmac

5
@lukmac据sed您所知,您DID提供了一个备份后缀。备份后缀为s/old_link/new_link/g。此后的下一个参数应该是编辑命令。因为它将命令解释为备份名称,所以它将第一个文件名作为编辑命令,但是它们无效。
2014年

2
这将永远是一个问题吗?Apple是否可以通过某种方式创建OSX所解决的GNU解决方案/程序包?或者,GNU无法支持sed sed -i '' -e ...吗?
blong

5
sed -i'' -e在Mac 10.14上似乎无法正常工作
MoOx

64

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

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

使用GNU sed扩展是可选的


55

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

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

或带备份:

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

注意-i选项后缺少空间!(GNU sed必需)


7
第一个在OSX上不起作用(我刚刚在10.6.8上进行了测试)
marcin

4
对于我来说,在OS X(10.10.3)上,第一个创建了后缀为-e的备份文件。不好。第二个是唯一在Ubuntu和OS X之间对我一致的东西。尽管我不希望备份文件,所以我必须rm在删除后立即运行命令。
布伦丹

1
第一行应改写为可以在10.10上工作的空间: sed -i'' ...=>sed -i '' ...
Daniel Jomphe

3
@DanielJomphe但是添加该空间对GNU sed不起作用
Brice

1
@marcin在OSX 10.11.2上也对我有效。唯一的事情是它将创建一个备份文件,然后需要将其删除。第二个看起来更好,因为我们以后不必弄清楚文件名了。
vikas027 '17

41

在Mac中遇到了相同的问题,并使用以下方法解决了该问题brew

brew install gnu-sed

并用作

gsed SED_COMMAND

您还可以设置sed别名gsed(如果需要):

alias sed=gsed

3
您为什么给出与Ohad Kravchick完全相同的答案
gniourf_gniourf

1
设置这样的别名不是一个好主意
SantaXL

1
代替别名(按照相应的brew页面中的建议),将其添加到路径:PATH =“ $(brew --prefix)/ opt / gnu-sed / libexec / gnubin:$ PATH”
y.luis


9

您的Mac确实确实运行了BASH shell,但这更多地是您要处理sed的哪种实现的问题。在Mac上,sed来自BSD,与典型的Linux机器上的sed略有不同。我建议你man sed


3
感谢您指出BSD的问题-但是我很文盲,只需要快速纠正命令即可-快速看完男人不会告诉我任何事情
Yarin

5
@Yarin-不,如果我快速浏览一下man sed,那也不会告诉您任何信息。尝试更长的时间。
高性能Mark

21
大多数SO答案都埋在一个人的某个地方,但这就是SO忙碌的人,他们需要聪明人的答案
Yarin

9

Sinetris的答案是正确的,但我将其与 find命令来更具体地说明我要更改的文件。通常,这应该可以工作(在osx上测试/bin/bash):

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

在使用一般sed没有find复杂项目中效率较低。


-exec是非常好的!我只是想知道到底是否真的需要斜线
刘烨

2
@YeLiu:如果没有\;我尝试这样做时,shell会解释它
serv-inc

2

我创建了一个函数来处理sedMacOS(在MacOS 10.12上测试)和其他OS之间的差异:

OS=`uname`
# $(replace_in_file pattern file)
function replace_in_file() {
    if [ "$OS" = 'Darwin' ]; then
        # for MacOS
        sed -i '' -e "$1" "$2"
    else
        # for Linux and Windows
        sed -i'' -e "$1" "$2"
    fi
}

用法:

$(replace_in_file 's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' "./mysql/.env")

哪里:

, 是一个分度

's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' 是模式

"./mysql/.env" 是文件的路径


1

这是将环境变量应用于模板文件的方法(无需备份)。

1.使用{{FOO}}创建模板以供以后替换。

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

2.用FOO变量替换{{FOO}}并输出到新的foo.conf文件

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

同时运行macOS 10.12.4Ubuntu 14.04.5


0

正如其他答案所表明的,没有一种方法可以在不制作备份文件的情况下跨OS X和Linux移植使用sed。因此,我改用了这种Ruby单一代码:

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

就我而言,我需要从一个rake任务中调用它(即在Ruby脚本中),所以我使用了附加的引用级别:

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

-1
sed -ie 's/old_link/new_link/g' *

在BSD和Linux上均可使用


3
这会在Linux上创建e附加的另一个文件名
Brice

1
坏了,最好将其删除。
索林

它适用于Mac和Linux。此解决方案有什么问题?
伊斯兰阿萨布(Azab)

不,它在Mac BSD Sed上不起作用-它将创建一个备份文件,并在文件名中添加“ e”。
Jesper Grann Laursen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.