sed命令与-i选项(就地编辑)在Ubuntu上工作正常,但不是Mac
我对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的帮助,点对点的答案 :
- 采用便携式解决scheme
- 与背景信息
tl; dr :
相当于这个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 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
有关说明,请参阅下文; 对于其他解决scheme,包括符合POSIX标准的解决scheme,请参阅我的相关答案 。
背景信息
在GNU sed
(大多数Linux发行版的标准)和BSD / macOS sed
, 执行其input文件就地更新 [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
是适用于可选选项参数的唯一forms。 - 语法
-i.bak
也作为强制选项参数使用,作为-i .bak
的替代方法 ,即分别指定选项及其参数。
不指定后缀 (通常是这种情况)意味着不应该保留备份文件 ,这就是不兼容的地方:
-
对于GNU
sed
,不指定后缀意味着简单地使用-i
本身 。 -
使用BSD / macOS
sed
,不指定后缀意味着将空string指定为 – mandatory – suffix, 由于技术原因,空string只能作为单独的parameter passing :即-i ''
-i''
。
-i''
不起作用,因为sed
与-i
不能区分 ,因为shell有效地删除了空引号(它将-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
参数满足后缀参数的语法要求。
这些备份文件的意外创build很容易被忽视,这是对Crt错误答案的最可能的解释,也是对类似问题获得如此多的赞成票的错误答案 (截至撰写本文)。
[1]严格来说,在后台创build临时文件,然后replace原始文件; 这种方法可能会有问题:请参阅我的答案的下半部分。
男人是你的朋友。
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中,您可以使用sed: gsed
的GNU版本。
# 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, eg: $SED -i "/ $domain .*#drupalpro/d" /etc/hosts
- javax.validation.ValidationException:HV000183:无法加载“javax.el.ExpressionFactory”
- 如何在MongoDB中按datesorting集合?