在Mac(BSD)和Linux上均可使用的sed in-place标志
是否有没有备份的sed
todo in-place编辑的调用,可以在Linux和Mac上使用? 尽pipeOS X附带的BSD sed
似乎需要sed -i '' …
,但是GNU sed
Linux发行版通常将解释为空input文件名(而不是备份扩展名),并且需要sed -i …
是否有任何命令行语法,这两种口味的作品,所以我可以在两个系统上使用相同的脚本?
如果你真的想用sed -i
'的方式,下面的工作在GNU和BSD / Mac sed
:
sed -i.bak 's/foo/bar/' filename
注意缺less空间和点。
certificate:
# 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上
- 因为备份文件的扩展
-e
被设置为-e
所以不能使用sed -i -e
-e
- 不能使用
sed -i'' -e
出于相同的原因,它需要在-i
和''
之间的空格。
在OSX上时,我总是通过Homebrew安装GNU sed版本,以避免在脚本中出现问题,因为大多数脚本都是为GNU sed版本编写的。
brew install gnu-sed --with-default-names
然后你的BSD sed将被GNU sedreplace。
或者,您可以安装没有默认名称,但是:
- 安装gnu-sed后按照说明更改PATH
- 检查你的脚本,根据你的系统selectgsed还是sed
没有办法让它工作。
一种方法是使用临时文件,如:
TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX` sed -e "s/abc/def/" some/file > $TMP_FILE mv $TMP_FILE some/file
这对两者都有效
答:不可以
最初接受的答案实际上并没有做到要求(正如评论中指出的那样)。 (当我查找file-e
在我的目录中随机出现的原因时,我find了这个答案。)
显然没有办法使sed -i
在MacOS和Linuces上始终如一地工作。
我的build议是,不要用sed
(具有复杂的故障模式)进行就地更新,而是生成新的文件并在之后对其进行重命名。 换句话说:避免-i
。
正如Noufal Ibrahim所问,为什么你不能使用Perl? 任何Mac都将具有Perl,并且很less有Linux或BSD发行版在基本系统中不包含某些版本的Perl。 可能实际上缺lessPerl的唯一环境之一是BusyBox(除了不能指定备份扩展外,其工作方式与GNU / Linux一样适用于-i
)。
正如伊斯梅尔build议的,
由于perl在任何地方都可用,我只要做
perl -pi -es,foo,bar,g target.file
这似乎是一个更好的解决scheme,几乎在任何情况下,脚本,别名,或其他解决scheme来处理基本不兼容的GNU / Linux和BSD / Mac之间的sed -i
。
Steve Powell的回答是非常正确的,在OSX和Linux(Ubuntu 12.04)上查阅MAN的页面,突出了在两个操作系统中就地使用sed的不兼容性。
JFYI,使用Linux版本的sed时,-i和任何引号(表示一个空文件扩展名)之间应该没有空格,因此
sed Linux手册页
#Linux sed -i""
和
sed OSX手册页
#OSX (notice the space after the '-i' argument) sed -i ""
我在一个脚本中使用了一个别名'd命令和一个bash'if'中' uname '的OS名输出。 尝试在variables中存储与操作系统相关的命令string在解释引号时被命中并错过。 为了扩展/使用脚本中定义的别名,需要使用“ shopt -s expand_aliases ”。 shopt的用法在这里处理。
-i
选项不是POSIX Sed的一部分。 更便携的方法是在Ex模式下使用Vim:
ex -sc '%s/alfa/bravo/|x' file
-
%
select所有行 -
取而代之
-
保存并closures
我遇到了这个问题。 唯一的快速解决scheme是将mac中的sedreplace为gnu版本:
brew install gnu-sed
如果您需要在bash
脚本中就地执行sed
,并且您不想使用.bkp文件创build就地,并且您有办法检测操作系统(例如使用ostype.sh ),那么下面这个用bash
shell内置的eval
应该可以工作:
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""`
你可以用海绵。 海绵是一个旧的unix程序,在moreutils软件包中find(包括ubuntu和debian,以及mac中的自制软件)。
它将缓冲来自pipe道的所有内容,等待pipe道closures(可能意味着input文件已经closures),然后覆盖:
从手册页 :
概要
sed'…'文件| grep'…'| 海绵文件
以下在Linux和OS X上适用于我:
sed -i' ' <expr> <file>
例如一个包含aaabbaaba
的文件
sed -i' ' 's/b/c/g' f
在Linux和Mac上都会产生aaaccaaca
。 请注意, 包含空格的引号string在-i
和string之间没有空格 。 单引号或双引号都可以工作。
在Linux上,我在Ubuntu 14.04.4下使用bash
4.3.11版本,在OS X 10.11.4 El Capitan(Darwin 15.4.0)下使用Mac版本3.2.57。