在Linux和Mac上是否都可以调用sed在没有备份的情况下进行就地编辑?虽然OS X附带的BSD sed似乎需要sed -i "…,但GNU sed Linux发行版通常会将引号解释为空的输入文件名(而不是备份扩展名),并且需要sed -i…。
是否有适用于这两种风格的命令行语法,以便我可以在两个系统上使用相同的脚本?
在Linux和Mac上是否都可以调用sed在没有备份的情况下进行就地编辑?虽然OS X附带的BSD sed似乎需要sed -i "…,但GNU sed Linux发行版通常会将引号解释为空的输入文件名(而不是备份扩展名),并且需要sed -i…。
是否有适用于这两种风格的命令行语法,以便我可以在两个系统上使用相同的脚本?
当前回答
问题是sed是一个流编辑器,因此就地编辑是一个非posix扩展,每个人实现它的方式都不同。这意味着对于就地编辑,您应该使用ed以获得最佳的可移植性。如。
ed -s foobar.txt <<<$',s/foo/bar/g\nw'
参见https://wiki.bash-hackers.org/howto/edit-ed。
其他回答
这适用于GNU sed,但不适用于OS X:
sed -i -e 's/foo/bar/' target.file
sed -i'' -e 's/foo/bar/' target.file
这适用于OS X,但不适用于GNU sed:
sed -i '' -e 's/foo/bar/' target.file
在OS X上
不能使用sed -i -e,因为备份文件的扩展名将被设置为-e 由于同样的原因,不能使用sed -i " -e -它需要在-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之间根本不兼容的问题时,这似乎是一个比脚本、别名或其他变通方法更好的解决方案。
如果你需要在bash脚本中执行sed in-place,并且你不希望in-place的结果是.bkp文件,并且你有一种方法来检测os(比如,使用ostype.sh),那么下面的bash shell内置eval的hack应该可以工作:
OSTYPE="$(bash ostype.sh)"
cat > myfile.txt <<"EOF"
1111
2222
EOF
if [ "$OSTYPE" == "osx" ]; then
ISED='-i ""'
else # $OSTYPE == linux64
ISED='-i""'
fi
eval sed $ISED 's/2222/bbbb/g' myfile.txt
ls
# GNU and OSX: still only myfile.txt there
cat myfile.txt
# GNU and OSX: both print:
# 1111
# bbbb
# NOTE:
# if you just use `sed $ISED 's/2222/bbbb/g' myfile.txt` without `eval`,
# then you will get a backup file with quotations in the file name,
# - that is, `myfile.txt""`
适用于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
回答:没有。
最初接受的答案实际上没有做到所要求的(如评论中所述)。(我在寻找文件-e在我的目录中“随机”出现的原因时找到了这个答案。)
显然没有办法让sed -i在MacOS和Linuces上一致地工作。
我的建议是,无论如何,不要使用sed进行就地更新(它具有复杂的故障模式),而是生成新文件,然后重命名它们。换句话说:避免-i。