补充microtherion's helpful, to-the-point answer:
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 之间差异的讨论,请参阅我的 this answer。
便携方法:
注意:这里的可移植意味着该命令适用于所讨论的两种实现。它在 POSIX 意义上是不可移植的,因为 the -i option is not POSIX-compliant.
# 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 标准的解决方案,请参阅我的 this related answer。
背景资料
在 GNU sed(大多数 Linux 发行版的标准)和 BSD/macOS sed 中,-i 选项,执行 就地更新[1]
其输入文件,接受一个 option-argument,它指定要更新的文件的 备份文件 使用什么 后缀(文件扩展名) 。
例如,在 both 实现中,以下将原始文件 file 保留为备份文件 file.bak:
sed -i.bak 's/foo/bar/' file # Keep original as 'file.bak'; NO SPACE between -i and .bak
即使with GNU sed the suffix argument is optional,而对于BSD/macOS sed it is mandatory,上述语法也适用于两种实现,因为直接将选项参数(.bak)与选项(@ 987654351@) - -i.bak,而不是 -i .bak - 既可以作为可选也可以作为强制选项参数:
- 语法
-i.bak是唯一适用于可选选项参数的形式。
- 语法
-i.bak also 用作强制 选项参数,作为-i .bak 的替代,即指定选项及其论点单独。
不指定后缀 - 通常情况下 - 意味着不应该保留备份文件,这就是出现不兼容性的地方:
-i'' 不起作用,因为对于 sed,它与 -i 无法区分,因为 shell 有效地删除 空引号(它连接 -i 和 '' 并使用语法函数删除引号),并且在 两种情况 中只传递 -i。
只要(有效地)指定了-i,next 参数被解释为选项参数:
sed -i 's/foo/bar/' file # BREAKS with BSD/macOS Sed
's/foo/bar/' - 用于 Sed script(命令) - 现在被解释为 suffix,单词 file 被解释为脚本。
将这样的词解释为脚本然后会导致模糊的错误消息,例如
sed: 1: "file": invalid command code f,
因为f 被解释为 Sed 命令(函数)。
类似地,有:
sed -i -e 's/foo/bar/' file # CREATES BACKUP FILE 'file-e'
-e 被解释为 suffix 参数,而不是 Sed 的 -e 选项(可用于指定 多个命令,如果需要)。
因此,您将获得一个后缀为 -e 的备份文件,而不是保留 NO 备份。
这个命令没有按预期工作不太明显,因为就地更新确实成功了,因为-e 参数满足了后缀参数的语法要求。
这些备份文件的意外创建很容易被忽视是Crt's incorrect answer 和this incorrect answer to a similar question 获得如此多的赞成票的最可能解释(截至撰写本文时)。
[1] 严格来说,是在后台创建一个临时文件,然后替换原始文件;这种方法可能会有问题:请参阅我的this answer 的下半部分。