我有一个文件列表和相应的行号,我想在其中执行替换:
s/LOG.error/LOG.warn
其他地方也可能发生这种情况,但我不想打扰这些行。如何使用 find 和 sed 来实现这一点?
该文件的格式如下:
FooBar.java 125
FooBar.java 180
FooBar2.java 128
这是我在寻找方法时发现的:
cat filenames.txt | xargs sed -i '<get-line-number-here>s/LOG.error/LOG.warn' <get-file-name-here>
答案1
您需要按目标文件将文件拆分为多个分区,然后sed -i
分别对每个文件执行操作。假设您已按文件名和行号按升序分组,则可以执行以下操作
awk '$1 != prev { if (prev) print "\047 " prev;
prev=$1;
printf "sed -i \047" }
{ print $2 "s/LOG\\.error/LOG.warn/" }
END { if (prev) print "\047 " prev }' filenames.txt | sh
如果第一列中的文件名不是单个标记,那么这是一个快速而肮脏的黑客攻击,它将以有趣且可能危险的方式被破坏。
我们基本上将您的文本文件重构为一系列sed
脚本。因此您的示例将变成
sed -i '125s/LOG\.error/LOG.warn
180s/LOG\.error/LOG.warn/
' FooBar.java
sed -i '128s/LOG\.error/LOG.warn/
' FooBar2.java
您会注意到,该脚本包含每个文件sh
一个脚本。sed
如果您使用的是 *BSD 平台(包括 Mac OS),则需要将其更改sed -i
为sed -i ''
Awk 中的"sed -i \047\047"
以便正确嵌入单引号而不干扰周围的 shell 引用(以便整行变成printf "sed -i \047\047 \047" }
(sic))。