我试图找出是否可以在单个sed命令中编辑一个文件,而无需手动将编辑的内容流到一个新文件中,然后将新文件重命名为原始文件名。

我尝试了-i选项,但是Solaris系统说-i是非法选项。还有别的办法吗?


当前回答

在一个系统中,sed没有编辑文件的能力,我认为更好的解决方案是使用perl:

perl -pi -e 's/foo/bar/g' file.txt

虽然这确实创建了一个临时文件,但它替换了原始文件,因为已经提供了一个空的就地后缀/扩展名。

其他回答

请注意,在OS X上运行此命令时,您可能会遇到奇怪的错误,如“无效命令代码”或其他奇怪的错误。要修复此问题,请尝试

sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>

这是因为在OSX版本的sed上,-i选项需要一个扩展参数,因此您的命令实际上被解析为扩展参数,文件路径被解释为命令代码。来源:https://stackoverflow.com/a/19457213

-i选项将编辑的内容传输到一个新文件中,然后在幕后重命名它。

例子:

sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

而在macOS上,你需要:

sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

就像《007:大破天幕杀机》中Moneypenny说的:“有时候旧的方法是最好的。” 金凯德后来也说过类似的话。

$ printf ',s/false/true/g\nw\n' | ed {YourFileHere}

快乐编辑到位。 增加了'\nw\n'来写入文件。很抱歉没有及时回复请求。

支持-i选项就地编辑文件的sed版本写入临时文件,然后重命名该文件。

或者,你可以只使用ed。例如,要更改文件file.txt中所有出现的foo为bar,你可以这样做:

echo ',s/foo/bar/g; w' | tr \; '\012' | ed -s file.txt

语法类似于sed,但肯定不完全相同。

即使没有-i支持sed,也可以很容易地编写一个脚本来完成这项工作。而不是sed -i 's/foo/bar/g'文件,你可以做内联文件sed 's/foo/bar/g'。这样的脚本编写起来很简单。例如:

#!/bin/sh
IN=$1
shift
trap 'rm -f "$tmp"' 0
tmp=$( mktemp )
<"$IN" "$@" >"$tmp" && cat "$tmp" > "$IN"  # preserve hard links

对于大多数用途应该是足够的。

mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt

应该保留所有硬链接,因为输出被直接返回以覆盖原始文件的内容,并且避免了对sed的任何特殊版本的需要。