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

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


当前回答

如果你真的想用“简单”的方式使用sed -i,下面的方法在GNU和BSD/Mac sed上都有效:

sed -i.bak 's/foo/bar/' filename

注意这里没有空格和圆点。

证明:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

显然,你可以删除。bak文件。

其他回答

-i选项不是POSIX Sed的一部分。一个更方便的方法是 在Ex模式下使用Vim:

ex -sc '%s/alfa/bravo/|x' file

%选择所有行 年代取代 保存并关闭

在OSX上,我总是通过Homebrew安装GNU sed版本,以避免在脚本中出现问题,因为大多数脚本都是为GNU sed版本编写的。

brew install gnu-sed --with-default-names

然后你的BSD sed将被GNU sed取代。

或者,你也可以不使用默认名称进行安装,但是:

安装gnu-sed后,根据提示更改PATH 是否根据您的系统检入脚本在gsed或sed之间进行选择

正如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之间根本不兼容的问题时,这似乎是一个比脚本、别名或其他变通方法更好的解决方案。

回答:没有。

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

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

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

适用于GNU系统和OSX的可移植脚本:

if [[ $(uname) == "Darwin" ]]; then
    SP=" " # Needed for portability with sed
fi

sed -i${SP}'' -e "s/foo/bar/g" -e "s/ping/pong/g" foobar.txt