我对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 ''
为了补充microtherion的有用的,切中要害的答案:
- 与便携式解决方案
- 附背景资料
tl;博士:
这个GNU sed
(大多数Linux发行版的标准)命令的等效:
sed -i 's/foo/bar/' file
这是 BSD/macOS sed
命令:
sed -i '' 's/foo/bar/' file # Note the '' as a *separate argument*
对于BSD/macOS sed
,以下命令do not根本不起作用:
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
的解释见下文;对于替代解决方案,包括posix兼容的解决方案,请参阅我的相关回答。
背景信息
在GNU sed
(大多数Linux发行版的标准)和BSD/macOS sed
中, -i
选项,执行就地更新[1]在其输入文件中,接受一个选项参数,该参数指定要用于备份文件的后缀(文件扩展名) 。
。,在两个实现中,以下命令保留原始文件file
作为备份文件file.bak
:
sed -i.bak 's/foo/bar/' file # Keep original as 'file.bak'; NO SPACE between -i and .bak
即使在GNU 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
's/foo/bar/'
-原本用于Sed 脚本(命令)-现在被解释为后缀,单词file
被解释为脚本。将这样的单词解释为脚本会导致模糊的错误消息,如sed: 1: "file": invalid command code f
,
因为f
被解释为Sed命令(函数)。
同样,:
sed -i -e 's/foo/bar/' file # CREATES BACKUP FILE 'file-e'
-e
被解释为后缀参数,而不是Sed的-e
选项(如果需要,可以用来指定多个命令)。
因此,不是保持NO备份,而是得到后缀为-e
的备份文件。
这个命令没有像预期的那样工作是不太明显的,因为就地更新确实成功了,假设后缀参数的语法要求由-e
参数满足。
这些备份文件的意外创建很容易被忽视,这是Crt错误答案的最有可能的解释,而这个类似问题的错误答案得到了如此多的支持(截至撰写本文时)。
[1]严格来说,一个临时文件是在后台创建的,然后替换原始文件;这种方法可能是有问题的:看看我这个答案的下半部分。
的人是你的朋友。
OS X -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