在Linux上使用sed进行文本替换(从文件中读取并保存到同一文件)

37

我想读取文件 "teste",进行一些“查找和替换”操作,并用结果覆盖“teste”文件。到目前为止我得到的最接近的解决方案是:

$cat teste
I have to find something
This is hard to find...
Find it wright now!

$sed -n 's/find/replace/w teste1' teste

$cat teste1
I have to replace something
This is hard to replace...

如果我尝试像这样保存到同一文件:

$sed -n 's/find/replace/w teste' teste
或:
$sed -n 's/find/replace/' teste > teste
结果将是一个空白文件...
我知道我错过了一些非常愚蠢的东西,但是任何帮助都会受到欢迎。
更新:根据大家的建议和这个链接:http://idolinux.blogspot.com/2008/08/sed-in-place-edit.html,这是我的更新代码:
sed -i -e 's/find/replace/g' teste 
9个回答

48
在Linux系统中,使用sed -i可以进行原地编辑。然而,历史上sed实际上是一个过滤程序,用于编辑一个管道流中的数据。对于这种情况,您需要先向临时文件写入内容,然后再将其重命名为原始文件。
产生空文件的原因是在运行命令之前,shell会打开并截断该文件。

非常感谢。在原地编辑方面,“ed”是否比“sed”更合适? - Roger
1
是的和不是的;ed 更适合原地编辑,但在脚本中使用不是很方便,这就是为什么 sed 增加了一个非标准(按照 POSIX 规范)的 -i 选项。 - geekosaur
那么,在Linux中进行原地查找和替换编辑,最好的工具是“sed”。这样说正确吗? - Roger
是的。或者使用perl -i,它做的事情基本相同(并且启发了将-i添加到sed中),但是比较重量级。 - geekosaur

24

You want: sed -i 's/foo/bar/g' file


2
在我的情况下,我需要使用-e前缀来表示表达式。 - Bogdan M.

7

您想使用"sed -i"。这将直接更新内容。


2

实际上,如果你使用 -i 标记,sed 将会复制你编辑的原始行。

因此,这可能是一个更好的方法:

sed -i -e 's/old/new/g' -e '/new/d' file

2
使用 Perl 进行原地编辑
perl -pi -w -e 's/foo/bar/g;' file.txt

或者

perl -pi -w -e 's/foo/bar/g;' files*

对于许多文件


2

MacOS 上,我尝试了很多方法都不行,但是经过一番研究,我找到了this answer

所以以下方法适用于 MacOS

sed -i '' -e 's/find/replace/g' teste 

然而,在我的管道中,对于Linux发行版,以下命令可以正常工作,而上述命令则会抛出错误:

sed -i -e 's/find/replace/g' teste 

1

有一个非常有用的sponge命令。

sponge命令会在打开输出文件之前吸取所有的输入。

$cat test.txt | sed 's/find/replace/w' | sponge test.txt

1

ed 的解决方案是:

ed teste <<END
1,$s/find/replace/g
w
q
END

或者不使用heredoc

printf "%s\n" '1,$s/find/replace/g' w q | ed teste

0
在Unix和Plan9中,适合您任务的另一个命令是tee。
sed 's/find/replace/'<file | tee file

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