Ersetzen Sie die Zeichenfolge mit der neuen Zeile in einer großen Datei

Ersetzen Sie die Zeichenfolge mit der neuen Zeile in einer großen Datei

Kennt jemand ein nicht zeilenbasiertes Tool zum „binären“ Suchen/Ersetzen von Zeichenfolgen auf eine einigermaßen speichereffiziente Weise?Sehendiese Fragezu.

Ich habe eine über 2 GB große Textdatei, die ich ähnlich wie folgt verarbeiten möchte:

sed -e 's/>\n/>/g'

Das bedeutet, ich möchte alle Zeilenumbrüche entfernen, die nach einem auftreten >, aber nirgendwo sonst, sodass ausgeschlossen ist tr -d.

Dieser Befehl (den ich vondie Antwort auf eine ähnliche Frage) schlägt fehl mit couldn't re-allocate memory:

sed --unbuffered ':a;N;$!ba;s/>\n/>/g'

Gibt es also andere Methoden, ohne auf C zurückzugreifen? Ich hasse Perl, bin aber in diesem Fall bereit, eine Ausnahme zu machen :-)

Ich kenne kein Zeichen mit Sicherheit, das in den Daten nicht vorkommt, daher \nmöchte ich das vorübergehende Ersetzen durch ein anderes Zeichen nach Möglichkeit vermeiden.

Hat irgendjemand eine gute Idee?

Antwort1

Das ist in Perl wirklich trivial, Sie sollten es nicht hassen!

perl -i.bak -pe 's/>\n/>/' file

Erläuterung

  • -i: Bearbeiten Sie die Datei an Ort und Stelle und erstellen Sie eine Sicherungskopie des Originals mit dem Namen file.bak. Wenn Sie keine Sicherungskopie möchten, verwenden Sie perl -i -pestattdessen einfach .
  • -pe: Lesen Sie die Eingabedatei Zeile für Zeile und drucken Sie jede Zeile aus, nachdem Sie das angegebene Skript angewendet haben -e.
  • s/>\n/>/: die Ersetzung, genau wie sed.

Und hier ist ein awkAnsatz:

awk  '{if(/>$/){printf "%s",$0}else{print}}' file2 

Antwort2

Eine perlLösung:

$ perl -pe 's/(?<=>)\n//'

Erläuterung

  • s///wird zur Zeichenfolgenersetzung verwendet.
  • (?<=>)ist ein Lookbehind-Muster.
  • \nentspricht der Zeilenumbruch.

>Das gesamte Muster bedeutet, dass alle davor stehenden Zeilenumbrüche entfernt werden .

Antwort3

Wie wäre es damit:

sed ':loop
  />$/ { N
    s/\n//
    b loop
  }' file

Für GNU sed können Sie auch versuchen, die Option -u( --unbuffered) gemäß der Frage hinzuzufügen. GNU sed ist auch mit einem einfachen Einzeiler zufrieden:

sed ':loop />$/ { N; s/\n//; b loop }' file

Antwort4

sedbietet keine Möglichkeit, Ausgaben ohne abschließende Zeilenumbrüche auszugeben. Ihr Ansatz mit Nfunktioniert grundsätzlich, speichert aber unvollständige Zeilen im Speicher und kann daher fehlschlagen, wenn die Zeilen zu lang werden (sed-Implementierungen sind normalerweise nicht für die Verarbeitung extrem langer Zeilen ausgelegt).

Sie können stattdessen awk verwenden.

awk '{if (/<$/) printf "%s", $0; else print}'

Ein alternativer Ansatz besteht darin, trdas Zeilenumbruchzeichen durch ein „langweiliges“, häufig vorkommendes Zeichen zu ersetzen. Leerzeichen könnte hier funktionieren – wählen Sie ein Zeichen, das in Ihren Daten in jeder Zeile oder zumindest in einem großen Teil der Zeilen vorkommt.

tr ' \n' '\n ' | sed 's/> />/g' | tr '\n ' ' \n'

verwandte Informationen