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 \n
mö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 Namenfile.bak
. Wenn Sie keine Sicherungskopie möchten, verwenden Sieperl -i -pe
stattdessen 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 wiesed
.
Und hier ist ein awk
Ansatz:
awk '{if(/>$/){printf "%s",$0}else{print}}' file2
Antwort2
Eine perl
Lösung:
$ perl -pe 's/(?<=>)\n//'
Erläuterung
s///
wird zur Zeichenfolgenersetzung verwendet.(?<=>)
ist ein Lookbehind-Muster.\n
entspricht 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
sed
bietet keine Möglichkeit, Ausgaben ohne abschließende Zeilenumbrüche auszugeben. Ihr Ansatz mit N
funktioniert 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, tr
das 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'