如何使用输入和输出作为同一文件运行sed命令?

时间:2012-05-31 07:55:54

标签: sed

我正在尝试在shell脚本中使用sed命令,我想删除读取STARTremoveThisComment的行和读取removeThisCommentEND的行。

当我使用

将其复制到新文件时,我可以这样做
sed 's/STARTremoveThisComment//' > test

但是如何通过使用与输入和输出相同的文件来完成此操作?

5 个答案:

答案 0 :(得分:80)

sed -i(或扩展版本--in-place)将自动执行通常使用不太高级的实现完成的过程,即将输出发送到临时文件,然后将其重命名为原始文件。

-i用于就地编辑,您还可以提供备份后缀以保留原始副本:

sed -i.bak fileToChange
sed --in-place=.bak fileToChange

这两个文件都会将原始文件保留在fileToChange.bak

请注意,就地编辑可能并非在所有sed实现中都可用,但 在GNU sed中可能适用于所有Linux版本,根据你的标签。

如果您使用的是更原始的实现,则可以使用以下内容:

sed 'whatever' oldfile >newfile ; mv newfile oldfile

虽然更多的错误检查会很好。

答案 1 :(得分:8)

您可以使用 -i 标记进行就地编辑,使用 -e 标记正常的脚本表达式:

sed -i -e 's/pattern_to_search/text_to_replace/' file.txt

要删除与特定模式匹配的行,您可以使用更简单的语法。注意 d 标志:

sed -i '/pattern_to_search/d' file.txt

答案 2 :(得分:5)

你真的不应该使用sed。这个问题似乎经常出现,并且看起来非常奇怪,因为一般的解决方案是如此微不足道,人们想知道如何在sed,python和ruby等中做到这一点似乎很奇怪。如果要对输入进行过滤操作并覆盖它,请使用以下简单脚本:

#!/bin/sh -e
in=${1?No input file specified}
mv $in ${bak=.$in.bak}
shift
"$@" < $bak > $in

将它放在路径中的可执行文件名inline中,然后问题就解决了。例如:

inline input-file sed -e s/foo/bar/g

现在,如果要添加逻辑以保留多个备份,或者如果您有一些选项来更改备份命名方案,或者其他任何选项,则可以在一个位置修复它。在使用perl就地处理文件时,在备份文件上获取1-up计数器的命令行选项是什么?用ruby怎么样? gnu-sed的选项是否有所不同? awk如何处理它? unix的全部意义在于工具只做一件事。处理备份文件的逻辑是第二件事,需要将其考虑在内。如果要实现工具,请不要添加逻辑来创建备份文件。告诉您的用户使用第二个工具。整合很糟糕。模块化很好。这就是unix方式。

请注意,此脚本存在一些问题。例如,可以改变输入文件的许可/模式。我确定还有无数其他问题。但是,通过将备份逻辑放在包装器脚本中,您可以本地化所有这些问题,而不必担心sed会覆盖文件和更改模式,而python会保留文件并且不改变inode(我编写了这两种情况,重点是不是所有工具都使用相同的逻辑,而包装脚本会。)

答案 3 :(得分:0)

据我所知,不可能使用相同的文件进行输入和输出。虽然一个解决方案是创建一个将其保存到另一个文件的shell脚本,但删除旧输入并将输出重命名为输入文件名。

sed -e s/try/this/g input.file > output.file;mv output.file input.file

答案 4 :(得分:0)

我建议使用sponge

  

sponge读取标准输入并将其写到指定文件中。   与shell重定向不同,海绵在写入之前先吸收所有输入   输出文件。这允许构建从和读取的管道   写入同一文件。

cat test | sed 's/STARTremoveThisComment//' | sponge test