複数のファイル内の行を置き換える

複数のファイル内の行を置き換える

置換を実行したいファイルと対応する行番号のリストがあります。

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

これは、各ファイルごとにsh1 つのスクリプトを含むスクリプトであることがわかります。sed

*BSD プラットフォーム (Mac OS を含む) を使用している場合は、周囲のシェルの引用符を乱すことなく一重引用符を適切に埋め込むために、Awk では にsed -i変更する必要があります(つまり、行全体が(sic) になります)。sed -i ''"sed -i \047\047"printf "sed -i \047\047 \047" }

関連情報