问题描述
||
是否可以调用“ 0”以进行就地编辑而不进行备份,而该备份在Linux和Mac上均有效? OS X附带的BSD
sed
似乎需要sed -i \'\' …
,而GNUsed
Linux发行版通常会随附将引号解释为空的输入文件名(而不是备份扩展名),而需要sed -i …
。
是否有任何两种语法都适用的命令行语法,所以我可以在两个系统上使用相同的脚本?
解决方法
如果您真的只想以\'easy \'方式使用ѭ5,那么以下方法在GNU和BSD / Macѭ0上都可以使用:
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
文件。
,这适用于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上,您
不能使用extension12ѭ,因为备份文件的扩展名将设置为-e
出于相同的原因,不能使用sed -i\'\' -e
,它需要在-i
和\'\'
之间留一个空格。
,在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。可能实际上缺少Perl的仅有的环境之一就是BusyBox(它与NU15 G的GNU / Linux一样工作,只是没有指定备份扩展名)。
按照ismail的建议,
由于perl随处可见,所以我只需perl -pi -e s,foo,bar,g target.file
在几乎所有情况下,这似乎都是比脚本,别名或其他替代方法更好的解决方案,用于解决GNU / Linux与BSD / Mac之间的ѭ5根本不兼容的问题。
,没有办法使其起作用。
一种方法是使用类似以下的临时文件:
TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX`
sed -e \"s/abc/def/\" some/file > $TMP_FILE
mv $TMP_FILE some/file
这对两个都有效
,答:不可以。
最初接受的答案实际上不执行要求的操作(如注释中所述)。 (我在查找file-e
在目录中出现“随机”的原因时找到了这个答案。)
显然没有办法让ѭ5在MacOS和Linuces上都能正常工作。
对于我来说,我的建议不是用with0ѭ(具有复杂的故障模式)就地更新,而是生成新文件并随后重命名它们。换句话说:避免-i
。
,-i
选项不属于POSIX Sed。一种更便携的方法是
在Ex模式下使用Vim:
ex -sc \'%s/alfa/bravo/|x\' file
%
选择所有行
s
更换
x
保存并关闭
,这是可以在Linux和macOS上运行而无需使用without35 using并且无需删除备份文件的另一个版本。它使用Bash数组存储sed
参数,比使用eval
更干净:
# Default case for Linux sed,just use \"-i\"
sedi=(-i)
case \"$(uname)\" in
# For macOS,use two parameters
Darwin*) sedi=(-i \"\")
esac
# Expand the parameters in the actual call to \"sed\"
sed \"${sedi[@]}\" -e \'s/foo/bar/\' target.file
这不会创建备份文件,也不会创建带有引号的文件。
,史蒂夫·鲍威尔(Steve Powell)的答案是非常正确的,请查阅MAN页面以在OSX和Linux上进行sed(Ubuntu 12.04),突出显示了两种操作系统在“就地”使用sed时的内部兼容性。
JFYI,使用Linux版本的sed -i和任何引号(表示空文件扩展名)之间不应有空格,因此
sed Linux手册页
#Linux
sed -i\"\"
和
sed OSX手册页
#OSX (notice the space after the \'-i\' argument)
sed -i \"\"
我通过在bash \'if \'中使用别名\'d命令和\'uname \'的操作系统名称输出来解决此问题。解释引号时,尝试将依赖于操作系统的命令字符串存储在变量中时会遇到麻烦。为了扩展/使用脚本中定义的别名,必须使用\'shopt -s expand_aliases \'。 shopt的用法在这里处理。
,我遇到了这个问题。唯一快速的解决方案是将mac中的sed替换为gnu版本:
brew install gnu-sed
,如果您需要在bash
脚本中就地执行sed
,并且不希望就地产生.bkp文件,那么您可以通过一种方法检测os(例如,使用ostype.sh),-那么下面的内置eval
的bash
外壳的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\"\"`
,您可以使用海绵。 Sponge是一个古老的unix程序,可在moreutils软件包中找到(在ubuntu和debian中都可以找到,在mac上的homebrew中都可以找到)。
它将缓冲管道中的所有内容,等待直到管道关闭(可能意味着输入文件已经关闭),然后覆盖:
从手册页:
概要
sed \'... \'文件| grep \'... \'|海绵锉
,以下内容适用于Linux和OS X:
sed -i\' \' <expr> <file>
例如用于包含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上使用。