使用 sed 或 awk 批量查找/替换

使用 sed 或 awk 批量查找/替换

在每个文件名与 pattern1 匹配的文件中,我想搜索以 pattern2 开头的行,并在这些匹配行上方的新行中添加一些字符串。

举一个简单的例子,假设我在 .txt 文件中递归搜索 potato,并且我想在上面添加 'spam',然后是文件 /tmp/blah.txt

hello
potato
world
not potato
bye

将转变为

hello
spam
potato
world
not potato
bye

对于 shell 向导来说,这听起来像是一项简单的工作,那么实现此目标的最简单方法是什么?我标记了一些我认为可能经常被怀疑的工具,但我愿意听取其他建议。如果它可以在我确认修改文件之前向我显示预览差异,那就更好了。

答案1

我也会在 Perl 中这样做:

$ for f in *txt; do perl -pne 'print "spam\n" if /^potato/' "$f"; done
hello
spam
potato
world
spam
not potato
bye

-p标志使 perl 打印输入文件的每一行。-n意思是“逐行读取输入文件”并将 给出的脚本应用于-e每一行。然后,脚本本身将打印spam当前行是否包含,并将打印每一行。结果将是打印在包含 的行上方的potato字符串。 spampotato

这将仅打印出新文件而不进行修改。如果您随后想对原始文件进行更改,请使用-i

$ for f in *txt; do perl -i.bak -pne 'print "spam\n" if /^potato/' "$f"; done

这将为每个处理过的文件创建一个名为的备份文件foo.txt.bak,并将更改应用于foo.txt

答案2

就我个人而言,我可能会使用 perl 来做这样的事情,但是你可以单独在 bash 中实现你想要的效果:

while read -r line ; do if [[ $line =~ "potato" ]]; then echo spam;  fi;  echo $line; done < file.txt

如果要将结果放入新文件中:

while read -r line ; do if [[ $line =~ "potato" ]]; then echo spam;  fi;  echo $line; done < file.txt > /tmp/outfile.txt

相关内容