在文件和覆盖文件中查找和替换不起作用,它会清空文件

时间:2011-03-02 18:44:28

标签: shell unix sed io-redirection

我想通过命令行在HTML文件上运行查找和替换。

我的命令看起来像这样:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html

当我运行它并在之后查看该文件时,它是空的。它删除了我文件的内容。

在我再次恢复文件后运行时:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

stdout是文件的内容,已执行查找和替换。

为什么会这样?

13 个答案:

答案 0 :(得分:876)

shell 在命令行中看到> index.html时,它会打开文件index.html以显示写入,同时擦除其以前的所有内容。< / p>

要解决此问题,您需要将-i选项传递给sed以进行内联更改,并在原始文件进行更改之前创建原始文件的备份:

sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

如果没有.bak,命令将在某些平台上失败,例如Mac OSX。

答案 1 :(得分:201)

另一种有用的模式是:

sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html

这有很多相同的效果,不使用-i选项,另外意味着,如果sed脚本由于某种原因失败,输入文件不会被破坏。此外,如果编辑成功,则没有剩余的备份文件。这种习语在Makefile中很有用。

相当多的seds有-i选项,但不是全部; posix sed是一个没有的。因此,如果您的目标是可移植性,那么最好避免使用。

答案 2 :(得分:86)

sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html

这会对文件index.html进行全局就地替换。引用字符串可以防止查询和替换中的空格问题。

答案 3 :(得分:56)

使用sed的-i选项,例如

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html

答案 4 :(得分:18)

要更改多个文件(并将每个文件的备份保存为* .bak):

perl -p -i -e "s/\|/x/g" *  

将获取目录中的所有文件,并将|替换为x 这被称为“Perl馅饼”(简单的馅饼)

答案 5 :(得分:14)

您应该尝试使用-i选项进行就地编辑。

答案 6 :(得分:6)

sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

如果您要添加要添加的链接,请尝试此操作。按上述方式搜索URL(以https开头,此处以..com结尾)并将其替换为URL字符串。我在这里使用了变量$pub_urls此处表示搜索,g表示全局替换。

有效!

答案 7 :(得分:4)

警告:这是一种危险的方法!它滥用了linux中的i / o缓冲区,并且具有缓冲的特定选项,可以处理小文件。这是一个有趣的好奇心。 但不要将其用于真实情况!

除了-i的{​​{1}}选项 您可以使用 sed实用程序

来自tee

  

tee - 从标准输入读取并写入标准输出和文件

所以,解决方案是:

man

- 这里重复sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html 以确保管道被缓冲。然后阻塞管道中的所有命令,直到它们获得一些输入为止。当上游命令将1个字节缓冲区(大小定义为somewhere)写入命令输入时,管道中的每个命令都会启动。因此,最后一个命令tee打开文件进行写入并因此将其清空,在上游管道完成并且输出位于管道内的缓冲区之后运行。

以下情况最有可能无效:

tee index.html

- 它将同时运行管道的两个命令而不会阻塞。 (不阻塞管道应该逐行传递字节而不是缓冲区缓冲区。与运行sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html 时相同。没有阻塞它更具交互性,通常只有2条命令的管道在没有缓冲和阻塞的情况下运行。更长的管道是缓冲。)cat | sed s/bar/GGG/将打开文件进行写入,它将被清空。但是,如果您始终打开缓冲,第二个版本也会起作用。

答案 8 :(得分:4)

命令问题

sed 'code' file > file

是在sed实际处理它之前,shell会截断file。结果,您得到一个空文件。

执行此操作的方法是使用-i进行编辑,就像其他答案所示。但是,这并不总是你想要的。 -i将创建一个临时文件,然后用于替换原始文件。如果您的原始文件是链接(链接将被常规文件替换),则会出现问题。如果需要保留链接,可以使用临时变量存储sed的输出,然后再将其写回文件,如下所示:

tmp=$(sed 'code' file); echo -n "$tmp" > file

更好的是,使用printf代替echo,因为echo可能会在某些shell中将\\处理为\(例如破折号):

tmp=$(sed 'code' file); printf "%s" "$tmp" > file

答案 9 :(得分:3)

ed回答:

printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html

要重申codaddict answered,shell会处理重定向第一次,消除“input.html”文件,然后 shell会调用“ sed“命令传递一个现在为空的文件。

答案 10 :(得分:2)

您可以在Ex模式下使用Vim:

ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
  1. %选择所有行

  2. x保存并关闭

答案 11 :(得分:0)

我正在寻找可以定义行范围并找到答案的选项。例如,我想从第36-57行将host1更改为host2。

__constant__

您也可以使用gi选项忽略字符大小写。

sed '36,57 s/host1/host2/g' myfile.txt > myfile1.txt

答案 12 :(得分:0)

如果对上述正确的答案充分尊重,那么“干运行”这样的脚本总是一个好主意,这样你就不会破坏你的文件而必须从头开始。

只需让你的脚本将输出溢出到命令行而不是将其写入文件,例如,像:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

OR

less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 

通过这种方式,您可以查看并检查命令的输出,而不会截断文件。