在原文件中直接编辑

507
如何在一个单独的sed命令中编辑文件?目前,我必须手动将编辑后的内容流式传输到一个新文件中,然后将新文件重命名为原始文件名。
我尝试了sed -i,但我的Solaris系统显示-i是一个非法选项。有其他方法吗?

11
-i 是 gnu sed 中的一个选项,但不属于标准 sed。使用该选项会将内容流式传输到新文件,然后将文件重命名,这可能不是您想要的。 - William Pursell
3
实际上,这正是我想要的。我只是希望不必执行重命名新文件为原始名称这种乏味任务时暴露身份。 - amphibient
3
那么你需要重新陈述问题。 - William Pursell
3
@amphibient: 你介意在你的问题标题前加上“Solaris”这个词吗?这样做可以增加你问题的价值。请查看我回答下面的评论。谢谢。 - Steve
2
@Steve:我再次从标题中删除了Solaris前缀,因为这绝不仅限于Solaris。 - tripleee
显示剩余2条评论
15个回答

3

您没有说明使用的是哪个shell,但是在zsh中,您可以使用=( )结构来实现这一点。大致如下:

cp =(sed ... file; sync) file

=()类似于>(),但会创建一个临时文件,当cp终止时该文件将自动删除。


2
为了解决这个问题,我需要在Mac上添加一些Unix函数到core-utils中,按照这里的方法进行操作。
brew install grep
==> Caveats
All commands have been installed with the prefix "g".
If you need to use these commands with their normal names, you
can add a "gnubin" directory to your PATH from your bashrc like:
  PATH="/usr/local/opt/grep/libexec/gnubin:$PATH"

建议使用gsed而非sed进行调用。因为Mac系统默认不喜欢grep -rl显示以./开头的文件名。

~/my-dir/configs$ grep -rl Promise . | xargs sed -i 's/Promise/Bluebird/g'

sed: 1: "./test_config.js": invalid command code .

我还必须使用xargs -I{} sed -i 's/Promise/Bluebird/g' {}来处理文件名中含有空格的文件。


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

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


只有在第一个命令意图为cp而不是mv时,这才有意义。 - undefined

1
非常好的例子。我曾经面临一个挑战,需要对许多文件进行原地编辑,使用“-i”选项似乎是在find命令中唯一合理的解决方案。这里是一个脚本,在每个文件的第一行前添加“version:”。
find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;

1

如果你想替换包含'/'的字符串,可以使用'?'。例如,将所有*.py文件中的'/usr/local/bin/python'替换为'/usr/bin/python3'。

find . -name \*.py -exec sed -i 's?/usr/local/bin/python?/usr/bin/python3?g' {} \;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接