Mehrere Such- und Ersetzungsaktionen in einer großen Textdatei

11

Ich habe eine große Textdatei (ca. 2 GB). Ich möchte fünf Such- und Ersetzungsaktionen für dieselbe Datei ausführen und möchte dies in einem Befehl ausführen. Normalerweise benutze ich vim, öffne die Datei, führe eine Ersetzungsaktion aus, dann die nächste usw. Es gibt einen Haken, da ich festgestellt habe, dass vim nach drei oder vier Suchvorgängen aufgrund von Speicherproblemen abstürzt.

Hier sind zwei Beispiele für den Befehl, den ich in Vim verwende:

:%s/www\.abcdef/www.test.abcdef/g 
:%s/www\.klmnop/www.test.klmnop/g

Was ist der beste Weg, um damit umzugehen?

SPRBRN
quelle

Antworten:

8

Ich würde sed so verwenden:

sed -i "s/www\.abcdef/www.test.abcdef/g;s/www\.kmlnop/www.test.klmnop/g;" yourfile.txt

-iOption steht für "an Ort und Stelle" Ersatz. Sie können sed -i.bakanweisen , eine Sicherung Ihrer Datei zu erstellen, die eine Erweiterung dieser Option bereitstellt ( sichert Ihre Datei.txt als Ihre Datei.txt.bak).

ssssteffff
quelle
Das ist schnell! Nicht nur Ihre Antwort ;-), sondern dieses Skript mit 5 Suchen und Ersetzen ist etwa 10x schneller als das Öffnen der Datei in vim. Eines hat mich allerdings verwirrt. Zuerst dachte ich, die .bak-Datei wäre die bearbeitete Datei, aber es ist natürlich das Original.
SPRBRN
Zehn Such- und Ersetzungsaktionen (mit Tausenden von Treffern) in einer 2-GB-Datei auf einmal, keine Speicherprobleme. Weniger als zwei Minuten auf einem durchschnittlichen Desktop - super!
SPRBRN
Eine Frage ... Sie entkommen den Punkten in der Ersetzungszeichenfolge. Ist das notwendig?
SPRBRN
1
Gern geschehen @rxt :) Eigentlich haben Sie Recht, Sie können nicht maskierte Punkte in der Ersatzzeichenfolge in verwenden sed. Ich habe es versucht und es funktioniert. Es gibt einen guten Thread in Unix & Linux Stackexchange , und die akzeptierte Antwort erwähnt keine Punkte als Zeichen, denen man entkommen kann.
ssssteffff
2
@rxt Sie sagten , Zeichenfolge ersetzen , sorry, nein, Sie müssen sie dort nicht entkommen.
Terdon
6

Wenn Sie viel mehr Suchmuster haben, können Sie diese in einer Datei speichern und die Ersetzungen von dort lesen. Angenommen, dies sind die Inhalte von replacements.txt:

www\.abcdef www.test.abcdef 
www\.klmnop www.test.klmnop

Sie können dann eine Liste von N Ersetzungen lesen und diese durch folgende ersetzen:

while read from to; do
  sed -i "s/$from/$to/" infile.txt ; 
done < replacements.txt 

ANMERKUNGEN:

  • Dies setzt voraus, dass Ihre Suchzeichenfolgen keine Leerzeichen enthalten und dass seltsame Zeichen maskiert werden müssen replacements.txt.
  • Es wird eine sedpro Austausch ausgeführt, was eine Weile dauern kann, wenn Sie viele Austauschvorgänge haben.
  • Es kann mit einer beliebigen Anzahl von Ersetzungen umgehen (Tausende oder Millionen oder was auch immer), solange Sie nichts dagegen haben, dass es etwas länger dauern wird.

Eine andere Möglichkeit wäre, das Obige als sedSkript zu schreiben :

s/www\.abcdef/www\.test\.abcdef/g;
s/www\.kmlnop/www\.test\.klmnop/g;
s/aaaa/bbbb/g;
s/cccc/dddd/g;
s/eeee/ffff/g;

Sie können das Skript dann in Ihrer Datei ausführen und alle Ersetzungen auf einmal vornehmen:

sed -f replace.sed infile.txt 
Terdon
quelle
+1 für die ,, andere Option ''. Könnte praktisch sein, um die Ersetzungen in einer Datei zu speichern! (Ich hoffe, ich werde mich daran erinnern ...)
mpy
+1 für die "andere Option", auch weil sie native Funktionen anstelle eines benutzerdefinierten Skripts verwendet und daher portabler / gemeinsam nutzbar ist
David Cook
@ DavidCook danke, aber es ist nicht nativer oder portabler als das andere. Der erste Ansatz verwendet eine POSIX-Shell-Schleife, die genauso portabel ist wie die zweite. Es wird nur viel langsamer sein, da es eine Shell-Schleife verwendet.
Terdon
Sie haben Recht, was ich damit gemeint habe, ist, dass das Dateiformat des sed-Skripts portabler ist, da es die eingebaute sed-Funktionalität anstelle eines Skripts verwendet, das neben der Datei replaceements.txt freigegeben werden müsste. Trotzdem sind beide gute Möglichkeiten!
David Cook