我正在尝试在shell脚本中使用sed命令,我想删除读取STARTremoveThisComment
的行和读取removeThisCommentEND
的行。
当我使用
将其复制到新文件时,我可以这样做sed 's/STARTremoveThisComment//' > test
但是如何通过使用与输入和输出相同的文件来完成此操作?
答案 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