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

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


当前回答

没有办法让它正常工作。

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

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

这对两者都有效

其他回答

问题是sed是一个流编辑器,因此就地编辑是一个非posix扩展,每个人实现它的方式都不同。这意味着对于就地编辑,您应该使用ed以获得最佳的可移植性。如。

ed -s foobar.txt <<<$',s/foo/bar/g\nw'

参见https://wiki.bash-hackers.org/howto/edit-ed。

以下是我在Linux和OS X上的工作:

Sed -i' ' <expr> <文件>

例如,对于包含aaabbaaba的文件f

Sed -i' 's/b/c/g' f

在Linux和Mac上生成aaaccaaca。注意,这里有一个带引号的字符串,其中包含一个空格,-i和字符串之间没有空格。单引号和双引号都可以。

在Linux上,我在Ubuntu 14.04.4下使用bash版本4.3.11,在OS X 10.11.4 El Capitan (Darwin 15.4.0)下使用Mac版本3.2.57。

如果你真的想用“简单”的方式使用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之间进行选择