904 Stimmen

Wie kann ich ein rekursives Suchen/Ersetzen einer Zeichenkette mit awk oder sed durchführen?

Wie finde und ersetze ich jedes Vorkommen von:

subdomainA.example.com

mit

subdomainB.example.com

in jeder Textdatei unter dem /home/www/ Verzeichnisbaum rekursiv?

114 Stimmen

Tipp: Führen Sie die folgenden Schritte nicht in einem svn-Checkout-Baum durch... es wird die magischen .svn-Ordnerdateien überschreiben.

9 Stimmen

Oh mein Gott, das ist genau das, was ich gerade getan habe. Aber es hat funktioniert und es scheint keinen Schaden angerichtet zu haben. Was könnte schlimmstenfalls passieren?

5 Stimmen

@J.Katzwinkel: Zumindest können die Prüfsummen beschädigt werden, was wiederum Ihr Repository beschädigen kann.

982voto

Nikita Fedyashev Punkte 16799
find /home/www \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'

-print0 sagt find um jedes der Ergebnisse durch ein Nullzeichen getrennt auszugeben, anstatt eine neue Zeile zu beginnen. Für den unwahrscheinlichen Fall, dass Ihr Verzeichnis Dateien mit Zeilenumbrüchen in den Namen enthält, können Sie damit immer noch xargs mit den richtigen Dateinamen arbeiten.

\( -type d -name .git -prune \) ist ein Ausdruck, der alle Verzeichnisse mit dem Namen .git . Sie können es leicht erweitern, wenn Sie SVN verwenden oder andere Ordner haben, die Sie beibehalten wollen - vergleichen Sie einfach mit mehr Namen. Es ist ungefähr gleichbedeutend mit -not -path .git Er ist jedoch effizienter, da er nicht jede Datei im Verzeichnis überprüft, sondern sie ganz überspringt. Die -o nachdem sie erforderlich ist, weil sie -prune tatsächlich funktioniert.

Weitere Informationen finden Sie unter man find .

491voto

Anatoly Punkte 4140

Der einfachste Weg ist für mich

grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'

308voto

John Zwinck Punkte 221200

Note : Führen Sie diesen Befehl nicht in einem Ordner aus, der ein Git-Repository enthält - Änderungen an .git könnten Ihren Git-Index beschädigen.

find /home/www/ -type f -exec \
    sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

Verglichen mit anderen Antworten hier ist diese einfacher als die meisten anderen und verwendet sed anstelle von Perl, wonach die ursprüngliche Frage fragte.

103voto

I159 Punkte 27156

Die Tricks sind fast alle gleich, aber dieser gefällt mir:

find <mydir> -type f -exec sed -i 's/<string1>/<string2>/g' {} +
  • find <mydir> : im Verzeichnis nachschlagen.

  • -type f :

    Datei ist vom Typ: reguläre Datei

  • -exec command {} + :

    Diese Variante der Aktion -exec führt den angegebenen Befehl für die ausgewählten Dateien aus, aber die Befehlszeile wird durch Anhängen von Die Gesamtzahl der Aufrufe des Befehls wird viel geringer sein als die Anzahl der ausgewählten Dateien. übereinstimmenden Dateien. Die Befehlszeile wird auf die gleiche Weise aufgebaut wie die Befehlszeilen von xargs. Nur eine Instanz von `{}' ist innerhalb des Befehls erlaubt. Das Kommando wird im Startverzeichnis ausgeführt.

53voto

Robert Lujo Punkte 14020

Die für mich am einfachsten zu merkende Lösung ist https://stackoverflow.com/a/2113224/565525 d.h.:

sed -i '' -e 's/subdomainA/subdomainB/g' $(find /home/www/ -type f)

ANMERKUNG : -i '' löst das OSX-Problem sed: 1: "...": invalid command code .

ANMERKUNG : Wenn es zu viele Dateien zu verarbeiten gibt, erhalten Sie Argument list too long . Die Umgehung - Verwendung find -exec o xargs oben beschriebene Lösung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X