2014-03-25 17 views
5

Ich habe Programm (gawk), das Datenstrom an seinen STDOUT ausgibt. Die verarbeiteten Daten sind buchstäblich 10 GB GB. Ich möchte es nicht in einer einzigen Datei persistieren, sondern es in Stücke teilen und möglicherweise einige zusätzliche Verarbeitung (wie die Komprimierung) auf jeden vor dem Speichern anwenden.STDIN in mehrere Dateien aufteilen (und wenn möglich komprimieren)

meine Daten sind eine Folge von Datensätzen, und ich möchte Splitting nicht in zwei Hälften schneiden. Jeder Datensatz entspricht den folgenden regulären Ausdruck:

^\{index.+?\}\}\n\{.+?\}$

oder die Einfachheit halber kann davon ausgehen, dass zwei Reihen (ersten uneben dann auch, wenn sie von Anfang der Streams Nummerierung) immer einen Datensatz machen.

Kann ich:

  • Verwendung einige Standard-Linux-Befehl zu spalten STDIN durch bevorzugte Größe von chunk definieren? Muss nicht genau angegeben werden, da die Größe der Datensatzvariablen dies nicht garantieren kann. Alternativ nur Anzahl der Datensätze, falls def. nach Größe
  • Kompresse jeder Chunk und speichern Sie in einer Datei nicht möglich ist (mit einiger Nummerierung in seinem Namen wie 001, 002 etc ..)

Ich habe wurde von Befehlen wie GNU parallel oder csplit aber don bewusst‘ Ich weiß, wie man es zusammenstellt. Wäre nett, wenn die oben beschriebene Funktionalität erreicht würde, ohne dafür ein eigenes Perl-Skript zu schreiben. Dies könnte jedoch eine andere, letzte Lösung sein, aber wiederum nicht sicher, wie man es am besten implementiert.

+0

Gibt es einen Grund, warum Sie 'split -l' nicht mit einer geraden Zahl für den Parameter' -l' verwenden können? Siehe: [Mann geteilt] (http://linux.die.net/man/1/split) –

+0

@PaulR gibt es - ich müsste zuerst den gesamten Datenstrom als eine physische Datei auf der Festplatte instanziieren. – msciwoj

Antwort

5

GNU Parallel kann stdin in Stücke von Datensätzen aufteilen. Dadurch wird stdin in 50-MB-Chunks aufgeteilt, wobei jeder Datensatz 2 Zeilen umfasst. Jeder Block wird weitergegeben an den Namen [chunk Nummer] gz gzip und komprimiert:

cat big | parallel -l2 --pipe --block 50m gzip ">"{#}.gz 

Wenn Sie wissen, Ihre zweite Zeile wird nie mit starten ‚{index‘ können Sie ‚{Index‘ als Rekord Start:

cat big | parallel --recstart '{index' --pipe --block 50m gzip ">"{#}.gz 

Sie können dann leicht testen, ob die Spaltung korrekt ging:

parallel zcat {} \| wc -l ::: *.gz 

es sei denn, Ihre Aufzeichnungen sind alle gleich lang werden Sie wahrscheinlich eine unterschiedliche Anzahl von Linien sehen, aber alle noch .

Sehen Sie das Intro-Video für eine schnelle Einführung: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Weg durch das Tutorial (Mann parallel_tutorial). Sie Befehlszeile werden Sie dafür lieben.

+0

OK, sieht sehr gut aus. Eine Frage jedoch - Parallel wird hier als Workaround verwendet, so dass es eher darum geht, den Datenstrom zu teilen, anstatt all diese Komprimierungsjobs gleichzeitig auszuführen. In meinem Fall ist das ein bisschen ein Problem, da die Maschine, die ich betreibe, eine niedrige Spezifikation hat. Könnte dies auf höchstens einen oder zwei nachgelagerte Jobs beschränkt sein? – msciwoj

+0

GNU Parallel führt _not_ nicht alle Jobs parallel aus.Es ist standardmäßig 1 Auftrag pro CPU-Kern. Sehen Sie sich die Intro-Videos an und gehen Sie durch das Tutorial, um zu erfahren, wie Sie den Standard ändern können. –

+0

Ich bekomme diese Nachricht zurück: parallel: Warnung: SIE VERWENDEN --tollef. WENN SACHEN VERSCHWINDEN --gnu. parallel: Achtung: --tollef veraltet und wird 20140222. parallel zurückgezogen werden: Achtung: Siehe: http://lists.gnu.org/archive/html/parallel/2013-02/msg00018.html /bin/bash: -c: Option erfordert ein Argument – msciwoj