我试图找出是否可以在单个sed命令中编辑一个文件,而无需手动将编辑的内容流到一个新文件中,然后将新文件重命名为原始文件名。
我尝试了-i选项,但是Solaris系统说-i是非法选项。还有别的办法吗?
我试图找出是否可以在单个sed命令中编辑一个文件,而无需手动将编辑的内容流到一个新文件中,然后将新文件重命名为原始文件名。
我尝试了-i选项,但是Solaris系统说-i是非法选项。还有别的办法吗?
当前回答
-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
其他回答
mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt
应该保留所有硬链接,因为输出被直接返回以覆盖原始文件的内容,并且避免了对sed的任何特殊版本的需要。
在一个系统中,sed没有编辑文件的能力,我认为更好的解决方案是使用perl:
perl -pi -e 's/foo/bar/g' file.txt
虽然这确实创建了一个临时文件,但它替换了原始文件,因为已经提供了一个空的就地后缀/扩展名。
-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
需要注意的一点是,sed不能自己写文件,因为sed的唯一目的是充当“流”(即stdin、stdout、stderr和其他>&n缓冲区、套接字等的管道)上的编辑器。考虑到这一点,您可以使用另一个命令tee将输出写回文件。另一种选择是创建一个补丁,从管道的内容到diff。
三通法
sed '/regex/' <file> | tee <file>
修补方法
sed '/regex/' <file> | diff -p <file> /dev/stdin | patch
更新:
另外,请注意patch将从diff输出的第一行获取要更改的文件:
Patch不需要知道要访问哪个文件,因为这在diff输出的第一行中找到:
$ echo foobar | tee fubar
$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin
*** fubar 2014-03-15 18:06:09.000000000 -0500
--- /dev/stdin 2014-03-15 18:06:41.000000000 -0500
***************
*** 1 ****
! foobar
--- 1 ----
! fubar
$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin | patch
patching file fubar
为了在Mac上解决这个问题,我不得不在core-utils中添加一些unix函数。
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'{}来处理名称中有空格的文件。