Testen Sie die rekursive Suche und ersetzen Sie sie, bevor Sie sie ausführen

13

Gibt es eine Möglichkeit, eine rekursive Testsuche und -ersetzung durchzuführen sed, bevor sie ausgeführt wird? Ich möchte nur die Ergebnisse ausdrucken, bevor ich wirklich suche und ersetze. So etwas wie das Echo der Ergebnisse von,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
user251482
quelle
Machen Sie eine Kopie der Daten, führen Sie Ihren Befehl aus und überprüfen Sie das Ergebnis.
Kusalananda

Antworten:

10

Sie könnten sedohne laufen -iund die Ausgabe mit schrittweise durchlaufenless

grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less

Führen Sie dann sedmit aus -i.bak, um Backups zu erstellen, die Sie anschließend unterscheiden können

grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct

Bearbeiten: Wie im Kommentar vorgeschlagen, verwenden Sie grep --null | xargs -0. Dadurch werden Dateinamen mit dem Null-Byte abgeschlossen, wodurch Dateinamen mit ungewöhnlichen Zeichen wie Newline geschützt sind. Ja, \nist ein gültiges Zeichen in einem Unix-Dateinamen. Die einzigen verbotenen Zeichen sind Schrägstriche /und Nullen\0

Grebneke
quelle
Interessanterweise habe ich versucht, die Bedeutung von -i zu finden, aber es wurde nicht unter man sed aufgeführt. Ihre Lösung hat funktioniert. Was wäre Ihrer Meinung nach der beste Weg, um nur die Zeilen aufzulisten, nicht die gesamte Datei? Anstatt in weniger zu pipen, pipte ich | grep term2, was irgendwie geklappt hat, aber ich habe auch einige Ausgaben mit seltsamen Zeichen bekommen.
user251482
@ user251482 - "Nur die Zeilen auflisten", wie unter "Unterschiede zwischen alter und neuer Datei anzeigen"?
Grebneke
1
@StephaneChazelas Ja, oder noch besser, grep -rl --nullda OP kein Betriebssystem spezifiziert hat und -Zunter BSD / OSX (Dekomprimierung) etwas anderes bedeutet. --nullist auf GNU und BSD gleich
grebneke
1
@grebneke. Guter Punkt, aber beachten Sie, dass das OP die GNU sed-Syntax verwendet, sodass wir davon ausgehen können, dass er kein BSD-Mitglied ist. Beachten Sie, dass dies grepeine Abzweigung von GNU grep unter FreeBSD und NetBSD ist. Unter NetBSD heißt das -Zimmer noch --null(laut Manpage), aber ich stimme zu, dass --null portabler ist. Beachten Sie auch, dass weder --null noch -Z unter OpenBSD
Stéphane Chazelas
1
@ Rebneke, es ist sed -i '' -e s/.../in BSD sed(keine optionalen Optionen gibt)
Stéphane Chazelas
5

Verwenden Sie sedmit findanstelle vongrep

Zunächst würde ich findeher als beschäftigen grep, und dies aus drei guten Gründen:

  1. findErmöglicht eine genauere Dateiauswahl. Beispielsweise grep -r string *.txtwerden Dateien nur im aktuellen Verzeichnis ausgegeben. nicht die in Unterverzeichnissen.
  2. findkommt mit der leistungsstarken -execOption, die das gesamte --null … |xargs 0Konstrukt überflüssig macht.
  3. Die Optionen -readableund -writablevon findverhindern, dass Zeit für Dateien verschwendet wird, auf die nicht zugegriffen werden kann.

Capture-Test

Das heißt, grepbietet sich für einen ersten Test an, um zu sehen, was erfasst werden würde:

$ find . -exec grep term1 {} \;

oder genauer:

$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;

Probelauf

Fahren Sie nun mit einem sedTrockenlauf fort. Die sedOption -nist ein Synonym für --quietund pam Ende des sedAusdrucks wird der aktuelle Musterbereich gedruckt.

$ find . -exec sed -n 's/term1/term2/gp' {} \;

oder genauer:

$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;

Ausführung

Wenn alles in Ordnung ist, setzen Sie den endgültigen Befehl ab, indem Sie die sedOption -ndurch -i"in place" ersetzen und die pam Ende stehende entfernen .

$ find . -exec sed -i 's/term1/term2/g' {} \;

oder genauer:

$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;

Weitere findBeispiele

Weitere findBeispiele finden Sie hier .

Serge Stroobandt
quelle