Wie teilt man eine große Datei in zwei Teile, nach einem Muster?
Ein Beispiel gegeben file.txt
:
ABC
EFG
XYZ
HIJ
KNL
Ich möchte diese Datei XYZ
so aufteilen, dass sie file1
die Zeilen bis zu XYZ
und den Rest der Zeilen enthält file2
.
text-processing
sed
awk
split
d.putto
quelle
quelle
XYZ
Zeile in die Ausgabe einbezogen werden oder nicht?Antworten:
Mit
awk
können Sie:Erläuterung: Das erste
awk
Argument (out=file1
) definiert eine Variable mit dem Dateinamen, die für die Ausgabe verwendet wird, während das nachfolgende Argument (largefile
) verarbeitet wird. Dasawk
Programm druckt alle Zeilen in die durch die Variableout
({print >out}
) angegebene Datei . Wenn das Muster gefundenXYZ
wird, wird die Ausgabevariable neu definiert, um auf die neue Datei ({out="file2}"
) zu verweisen, die als Ziel zum Drucken der nachfolgenden Datenzeilen verwendet wird.Verweise:
quelle
Dies ist ein Job für
csplit
:würde
s
ilently die Akte aufteilen und Stücke mit pre verursachenf
ixfile
undn
umbered eine einzelne Ziffer, zB unter Verwendungfile0
usw. Beachten Sie, dass mit/regex/
, würde sich trennen , aber nicht einschließlich der Linie , dass Streichhölzerregex
. Fügen Sie einen Versatz hinzu, um die Zeilenübereinstimmung aufzuteilen und einzuschließen:regex
+1
Dadurch entstehen zwei Dateien,
file0
undfile1
. Wenn Sie unbedingt einen Namen benötigenfile1
undfile2
demcsplit
Befehl immer ein leeres Muster hinzufügen und die erste Datei entfernen möchten:schafft
file0
,file1
undfile2
dochfile0
ist leer , so dass Sie es sicher entfernen können:quelle
Mit einem modernen
ksh
hier ist eine Shell-Variante (dh ohnesed
) einer dersed
oben genannten Antworten:Und noch eine Variante in
ksh
alleine (also auch weglassencat
):(Die reine
ksh
Lösung scheint ziemlich performant zu sein; bei einer 2,4-GB-Testdatei dauerte es 19-21 Sekunden, verglichen mit 39-47 Sekunden bei dersed
/cat
-basierten Ansatz).quelle
read
undprint
- Sie sollten es einfach gehen lassen, um alles selbst auszugeben. Die Leistung wird besser, wenn Sie das AST-Toolkit vollständigksh
erstellen und alle eingebauten Komponenten kompilieren - für michsed
ist es seltsam, dass dies eigentlich keine davon ist. Aber beiwhile <file do
sed
awk
Ihre Benchmark entwickelt? Und obwohl ich mir ziemlich sicher binksh
, dass Sie diesen Kampf wahrscheinlich immer gewinnen werden, sind Sie mit GNUsed
nicht sehr fair umzugehensed
- GNUs-u
nbuffered ist ein pissarmer Ansatz für POSIXLY, um sicherzustellen, dass der Offset des Deskriptors dort verbleibt, wo das Programm beendet wird Es sollte keine Notwendigkeit bestehen, den regulären Betrieb des Programms zu verlangsamen. Die Pufferung ist in Ordnung. Allessed
, was Sie tun müssen, ist, den Deskriptor zu suchen, wenn Sie fertig sind. Aus irgendeinem Grund kehrt GNU diese Mentalität um.while
; Das Drucken erfolgt implizit als definierter Nebeneffekt des<##
Umleitungsoperators. Und nur die passende Zeile muss gedruckt werden. (Auf diese Weise ist die Implementierung des Shell-Features für die Unterstützung von incl./excl am flexibelsten.) Eine explizitewhile
Schleife ist vermutlich wesentlich langsamer (wurde jedoch nicht überprüft).head
anstelle derread
; es scheint nur ein wenig langsamer, aber es ist knapperer Code:{ head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3
.Bei GNU
sed
sollten Sie den-u
Schalter nbuffered verwenden. Die meisten anderensed
s sollten jedoch funktionieren.XYZ weglassen ...
quelle
Versuchen Sie dies mit GNU sed:
quelle
sed -e '1,/XYZ/{w file1' -e 'd}' large_file > file2
Ein einfacher Hack besteht darin, entweder auf STDOUT oder STDERR zu drucken, je nachdem, ob das Zielmuster übereinstimmt. Sie können dann die Umleitungsoperatoren der Shell verwenden , um die Ausgabe entsprechend umzuleiten. Beispiel: In Perl wird angenommen, dass die Eingabedatei aufgerufen wird
f
und die beiden Ausgabedateienf1
undf2
:Verwerfen der Linie, die dem Aufteilungsmuster entspricht:
Einschließlich der übereinstimmenden Zeile:
Alternativ können Sie auch in andere Dateizugriffsnummern drucken:
Verwerfen der Linie, die dem Aufteilungsmuster entspricht:
Einschließlich der übereinstimmenden Zeile:
quelle