在Linux和Mac上是否都可以调用sed在没有备份的情况下进行就地编辑?虽然OS X附带的BSD sed似乎需要sed -i "…,但GNU sed Linux发行版通常会将引号解释为空的输入文件名(而不是备份扩展名),并且需要sed -i…。

是否有适用于这两种风格的命令行语法,以便我可以在两个系统上使用相同的脚本?


当前回答

正如Noufal Ibrahim所问的,为什么不能使用Perl?任何Mac都会有Perl,而且很少有Linux或BSD发行版在基本系统中不包含某些版本的Perl。BusyBox是唯一可能缺少Perl的环境之一(对于-i,它的工作方式与GNU/Linux类似,只是不能指定备份扩展)。

正如ismail所建议的,

由于perl在任何地方都可用,我只是做perl -pi -e s,foo,bar,g target.file

在处理sed -i在GNU/Linux和BSD/Mac之间根本不兼容的问题时,这似乎是一个比脚本、别名或其他变通方法更好的解决方案。

其他回答

你可以用海绵。海绵是一个老的unix程序,在moreutils包中找到(在ubuntu和debian中都有,在mac的homebrew中也有)。

它会缓冲管道中的所有内容,直到管道关闭(可能意味着输入文件已经关闭),然后覆盖:

从手册页:

剧情简介 sed的……' file | grep '…|海绵文件

正如Noufal Ibrahim所问的,为什么不能使用Perl?任何Mac都会有Perl,而且很少有Linux或BSD发行版在基本系统中不包含某些版本的Perl。BusyBox是唯一可能缺少Perl的环境之一(对于-i,它的工作方式与GNU/Linux类似,只是不能指定备份扩展)。

正如ismail所建议的,

由于perl在任何地方都可用,我只是做perl -pi -e s,foo,bar,g target.file

在处理sed -i在GNU/Linux和BSD/Mac之间根本不兼容的问题时,这似乎是一个比脚本、别名或其他变通方法更好的解决方案。

没有办法让它正常工作。

一种方法是使用临时文件,比如:

TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX`
sed -e "s/abc/def/" some/file > $TMP_FILE
mv $TMP_FILE some/file

这对两者都有效

Steve Powell的回答是非常正确的,在OSX和Linux (Ubuntu 12.04)上查阅sed的MAN页面强调了两个操作系统中“就地”sed使用的不兼容性。

JFYI,使用Linux版本的sed, -i和任何引号(表示空文件扩展名)之间不应该有空格,因此

sed Linux手册

#Linux
sed -i"" 

and

药效发作

#OSX (notice the space after the '-i' argument)
sed -i "" 

我在一个脚本中通过使用alias'd命令和bash 'if'中的'uname'的OS-name输出来解决这个问题。在解释引号时,试图将依赖于操作系统的命令字符串存储在变量中是错误的。为了扩展/使用脚本中定义的别名,必须使用'shopt -s expand_aliases'。这里讨论Shopt的用法。

回答:没有。

最初接受的答案实际上没有做到所要求的(如评论中所述)。(我在寻找文件-e在我的目录中“随机”出现的原因时找到了这个答案。)

显然没有办法让sed -i在MacOS和Linuces上一致地工作。

我的建议是,无论如何,不要使用sed进行就地更新(它具有复杂的故障模式),而是生成新文件,然后重命名它们。换句话说:避免-i。