我对sed一无所知,但需要这个命令(在Ubuntu上正常工作)在Mac OSX上也能正常运行:
sed -i "/ $domain .*#drupalpro/d" /etc/hosts
我得到了:
sed: 1: "/etc/hosts": extra characters at the end of h command
我对sed一无所知,但需要这个命令(在Ubuntu上正常工作)在Mac OSX上也能正常运行:
sed -i "/ $domain .*#drupalpro/d" /etc/hosts
我得到了:
sed: 1: "/etc/hosts": extra characters at the end of h command
Ubuntu预装GNU sed
,其中-i
选项的后缀是可选的。而OS X则预装BSD sed
,其中该后缀是强制性的。请尝试使用sed -i ''
。
sed -i '' '1i export PATH="$HOME/.composer/vendor/bin:$PATH"' $HOME/.bashrc
。 - microtherion.bak
),并将其附加到-i
选项中—— sed -i.bak …
。如果不这样做,则该脚本将无法在其中一个平台上正确操作。GNU sed
不喜欢 BSD sed
需要一个空参数才能原地编辑;你不能将空参数附加到 -i
上,因为它是空的,并且无法与 -i
区分。此外,由于设计上的矛盾,-i
选项也不会作为 -i
标准化为 POSIX;无法调和不可调和的冲突。 - Jonathan Lefflersed
命令后运行rm -f /etc/hosts.bak
来删除备份。这比尝试确定安装的sed
变体或其他建议中提到的小工具更简单。希望你能对文件进行版本控制(或备份),以便在sed
脚本出现错误时进行恢复。当然,.bak
文件为你提供了这种保护。 - Jonathan Lefflersed -i 's/foo/bar/' file
sed
命令:sed -i '' 's/foo/bar/' file # Note the '' as a *separate argument*
sed -i 's/foo/bar/' file # Breaks; script is misinterpreted as backup-file suffix
sed -i'' 's/foo/bar/' file # Ditto
sed -i -e 's/foo/bar/' file # -e is misinterpreted as backup-file suffix
关于 GNU sed
和 BSD/macOS sed
之间的所有差异的讨论,请参见我的 这个答案。
可移植方法:
注:这里的“可移植”是指该命令适用于所讨论的两种实现。它在 POSIX 意义上不是可移植的,因为 -i
选项不符合 POSIX 标准。
# Works with both GNU and BSD/macOS Sed, due to a *non-empty* option-argument:
# Create a backup file *temporarily* and remove it on success.
sed -i.bak 's/foo/bar/' file && rm file.bak
在大多数Linux发行版中,GNUsed
和BSD/macOSsed
都是标准的。这两个实现都有一个-i
选项,它执行输入文件的原地更新[1],接受一个选项参数,指定要用于正在更新的文件的备份文件的后缀名(文件扩展名)。
例如,在两个实现中,以下命令将原始文件file
保留为备份文件file.bak
:
sed -i.bak 's/foo/bar/' file # Keep original as 'file.bak'; NO SPACE between -i and .bak
sed
时,后缀参数是可选的, 而使用BSD/macOS sed
时,它是强制性的, 但上述语法在两种实现中都可以工作,因为直接将选项参数(.bak
)与选项(-i
)相邻 - -i.bak
,而不是 -i .bak
- 既可以作为可选的选项参数,也可以作为强制性的选项参数。
-i.bak
是唯一适用于可选选项参数的形式。-i.bak
也可以作为必选选项参数的形式,作为 -i .bak
的替代方案,即分别指定选项及其参数。不指定后缀(通常是这种情况)意味着不保留备份文件,这就是不兼容性产生的原因:
使用 GNU 的 sed
,不指定后缀意味着仅使用 -i
本身。
使用 BSD/macOS 的 sed
,不指定后缀意味着将空字符串指定为必需的后缀,并且由于技术原因,空字符串只能作为单独的参数传递:即 -i ''
不是 -i''
。
-i''
不起作用,因为对于 sed
来说,它与仅使用 -i
是无法区分的,因为 shell 实际上会删除空引号(它将 -i
和 ''
连接并删除具有语法功能的引号),并在两种情况下都只传递 -i
。
-i
选项,才会将下一个参数解释为选项参数。sed -i 's/foo/bar/' file # BREAKS with BSD/macOS Sed
file
则被解释为脚本。sed: 1: "file": invalid command code f
,f
被解释为 Sed 命令(函数)。
类似地,使用以下内容:
sed -i -e 's/foo/bar/' file # CREATES BACKUP FILE 'file-e'
mv file file.bak && sed 's/foo/bar/' file.bak > file && rm file.bak
是否可行? - Cássio Renan人是你的朋友。
-i extension
Edit files in-place, saving backups with the specified extension.
If a zero-length extension is given, no backup will be saved. It
is not recommended to give a zero-length extension when in-place
editing files, as you risk corruption or partial content in situ-
ations where disk space is exhausted, etc.
在OS X操作系统中,您可以使用GNU版本的sed:gsed
。
# if using brew
brew install gnu-sed
#if using ports
sudo port install gsed
然后,如果您的脚本需要可移植性,您可以根据您的操作系统定义要使用哪个命令。
SED=sed
unamestr=`uname`
if [[ "$unamestr" == "Darwin" ]] ; then
SED=gsed
type $SED >/dev/null 2>&1 || {
echo >&2 "$SED it's not installed. Try: brew install gnu-sed" ;
exit 1;
}
fi
# here your sed command, e.g.:
$SED -i "/ $domain .*#drupalpro/d" /etc/hosts