我对 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 ''
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
,以下命令根本无法正常工作或无法按预期工作:
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和 BSD/macOS之间所有差异的讨论,请参阅我的这个答案。sed
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
中,执行其输入文件的就地更新[1]的选项
接受一个选项参数,该选项指定用于备份文件的后缀(文件扩展名)正在更新的文件-i
。
例如,在这两种实现中,以下将原始文件 , 保留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 ''
not -i''
。
-i''
不起作用,因为sed
它与 just 无法区分-i
,因为shell有效地删除了空引号(它使用句法函数连接和删除引号),并且-i
在两种情况下都通过。''
-i
(有效地)刚刚-i
指定,下一个参数被解释为选项参数:
sed -i 's/foo/bar/' file # BREAKS with BSD/macOS Sed
's/foo/bar/'
- 用于 Sed脚本(命令) - 现在被解释为suffix,并且单词file
被解释为脚本。
将这样的单词解释为 script 然后会导致模糊的错误消息,例如
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] 严格来说,是在后台创建一个临时文件,然后替换原始文件;这种方法可能会出现问题:请参阅我的这个答案的下半部分。
男人是你的朋友。
-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