Ich habe eine Liste von Dateien und entsprechenden Zeilennummern, in denen ich die Ersetzung durchführen möchte:
s/LOG.error/LOG.warn
Es gibt andere Stellen, an denen dies auftreten könnte, und ich möchte diese Zeilen nicht stören. Wie kann ich dies mit find und sed tun?
Die Datei ist wie folgt formatiert:
FooBar.java 125
FooBar.java 180
FooBar2.java 128
Das habe ich gefunden, als ich nach einer Möglichkeit gesucht habe, dies zu tun:
cat filenames.txt | xargs sed -i '<get-line-number-here>s/LOG.error/LOG.warn' <get-file-name-here>
Antwort1
Sie müssen die Datei nach Zieldatei in Partitionen aufteilen und sed -i
jede Datei einzeln bearbeiten. Vorausgesetzt, Sie haben die Dateinamen und Zeilennummern nach Dateinamen und in aufsteigender Reihenfolge gruppiert, können Sie so etwas tun wie
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
Dies ist ein schneller und einfacher Hack, der auf interessante und möglicherweise gefährliche Weise kaputt geht, wenn die Dateinamen in der ersten Spalte nicht aus einem einzelnen Token bestehen.
Wir refaktorisieren Ihre Textdatei im Grunde in eine Folge von sed
Skripten. Ihr Beispiel wird also umgewandelt in
sed -i '125s/LOG\.error/LOG.warn
180s/LOG\.error/LOG.warn/
' FooBar.java
sed -i '128s/LOG\.error/LOG.warn/
' FooBar2.java
Sie werden feststellen, dass es sich um ein Skript handelt, das für jede Datei sh
ein Skript enthält .sed
Wenn Sie eine *BSD-Plattform (einschließlich Mac OS) verwenden, müssen Sie „which in Awk“ ändern, sed -i
um sed -i ''
einfache "sed -i \047\047"
Anführungszeichen richtig einzubetten, ohne die umgebenden Anführungszeichen der Shell zu beeinträchtigen (sodass die gesamte Zeile zu printf "sed -i \047\047 \047" }
„(sic)“ wird).