sed就位标志,在Mac(BSD)和Linux上均可使用

|| 是否可以调用“ 0”以进行就地编辑而不进行备份,而该备份在Linux和Mac上均有效? OS X附带的BSD
sed
似乎需要
sed -i \'\' …
,而GNU
sed
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上使用。     

要回复问题请先登录注册