Ich habe eine Textdatei mit dem Namen entry.txt
, die Folgendes enthält:
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Ich möchte es in drei Textdateien aufgeteilt: entry1.txt
, entry2.txt
, entry3.txt
. Ihre Inhalte sind wie folgt.
entry1.txt :
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
entry2.txt :
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
entry3.txt :
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Mit anderen Worten, das [
Zeichen gibt an, dass eine neue Datei beginnen soll. Die Einträge ( [ entry*]
wobei *
eine ganze Zahl ist) sind immer in numerischer Reihenfolge und sind aufeinanderfolgende ganze Zahlen von 1 bis N (in meiner tatsächlichen Eingabedatei N = 200001).
Gibt es eine Möglichkeit, die automatische Aufteilung von Textdateien in Bash durchzuführen? Meine eigentliche Eingabe entry.txt
enthält tatsächlich 200.001 Einträge.
quelle
match
Eintrag:/^\[/ { name=$2 }
sollte ausreichen.[ blahblah blah blah ]
in meiner Antwort verwendet.FS
, z-F '\\[ | \\]'
.#S x
, wobei x eine 1-, 2- oder 3-stellige Zahl ist. Das Speichern in x.dat würde ausreichen. Ich habe versucht:gawk '/^#S/{match($0, / [0-9]* /, k)} {print >k[1]".dat" }' myFile.txt
und einige Variationen davon.gawk '/^#S/{match($0, /^#S (\s+?)([0-9]+)(\s+?)/, k)} {print >k[2]".txt" }' test.txt
. Verstehe die Array-Nummer allerdings nicht2
sehr gut.Mit csplit von GNU coreutils (nicht eingebettetes Linux, Cygwin):
Am Ende erhalten Sie eine zusätzliche leere Datei
entry0.txt
(die den Teil vor dem ersten Header enthält).In Standard- csplit fehlen der
{*}
unbestimmte Repeater und die-b
Option, das Suffix-Format anzugeben. In anderen Systemen müssen Sie also zuerst die Anzahl der Abschnitte zählen und anschließend die Ausgabedateien umbenennen.quelle
In Perl kann es viel einfacher gemacht werden:
quelle
Hier ist ein kurzer Awk-Einzeiler:
Wie funktioniert das?
/^\[/
Stimmt mit Zeilen überein, die mit einer eckigen Klammer links beginnen, und{ofn=$2 ".txt"}
Setzt eine Variable auf das zweite Wort mit weißem Abstand als unseren Ausgabedateinamen. Dann,ofn
ist eine Bedingung, die als wahr ausgewertet wird, wenn die Variable gesetzt ist (wodurch Zeilen vor dem ersten Header ignoriert werden).{print > ofn}
Leitet die aktuelle Zeile in die angegebene Datei um.Beachten Sie, dass alle Leerzeichen in diesem awk-Skript entfernt werden können, wenn die Kompaktheit Sie glücklich macht.
Beachten Sie auch, dass das obige Skript wirklich die Abschnittsüberschriften benötigt, um Leerzeichen zu haben und nicht in ihnen. Wenn Sie in der Lage sein möchten, mit Abschnittsüberschriften wie
[foo]
und[ this that ]
umzugehen, benötigen Sie so etwas mehr Code:Hierbei wird die awk-
sub()
Funktion verwendet, um führende und nachfolgende eckige Klammern plus Leerzeichen zu entfernen. Beachten Sie, dass durch das standardmäßige awk-Verhalten Leerzeichen (das Feldtrennzeichen) in ein einzelnes Leerzeichen reduziert werden (dh[ this that ]
in gespeichert werden"this that.txt"
). Wenn es wichtig ist, das ursprüngliche Leerzeichen in den Ausgabedateinamen beizubehalten, können Sie durch Festlegen von FS experimentieren.quelle
Dies kann über die Befehlszeile in Python erfolgen:
quelle
Dies ist eine etwas grobe, aber leicht verständliche Methode: Verwenden Sie
grep -l '[ entry ]' FILENAME
, um die Zeilennummern bei [entry] aufzuteilen. Verwenden Sie eine Kombination aus Kopf und Schwanz, um die richtigen Teile zu erhalten.Wie ich sagte; es ist nicht schön, aber leicht zu verstehen.
quelle
Was ist mit awk
[
als Datensatztrennzeichen und Leerzeichen als Feldtrennzeichen ? Dies gibt uns leicht die Daten, die in der Datei abgelegt werden sollen,$0
wo er den entfernten Anfangsbuchstaben[
und den Dateinamen als zurücklegen muss$1
. Wir müssen dann nur den Sonderfall des 1. Datensatzes behandeln, der leer ist. Das gibt uns:quelle
Terdons Antwort funktioniert für mich, aber ich musste Gawk benutzen, nicht awk. Das Handbuch zu gawk (suche nach 'match (')) erklärt, dass das Array-Argument in match () eine gawk-Erweiterung ist. Vielleicht hängt es von deiner Linux-Installation und deinen awk / nawk / gawk-Versionen ab, aber auf meinem Ubuntu-Rechner lief nur gawk terdon's excellent Antworten:
quelle
Hier ist eine Perl-Lösung. Dieses Skript erkennt die
[ entryN ]
Zeilen und ändert die Ausgabedatei entsprechend, überprüft, analysiert oder verarbeitet jedoch nicht die Daten in den einzelnen Abschnitten, sondern druckt nur die Eingabezeile in die Ausgabedatei.quelle
Hallo, ich habe dieses einfache Skript mit Ruby geschrieben, um Ihr Problem zu lösen
du kannst es so benutzen:
Ich habe es getestet, und es funktioniert gut ..
quelle
Ich bevorzuge die
csplit
Option, aber als Alternative gibt es hier eine GNU awk-Lösung:parse.awk
Führen Sie es so aus:
quelle
RT
scheint die Variable gawk-spezifisch zu sein. Diese Lösung funktioniert mit FreeBSD awk nicht.