Neuindizierung einer großen CSV-Datei

11

Ich habe die Antworten in diesem hilfreichen Thread durchgesehen , aber mein Problem scheint so unterschiedlich zu sein, dass mir (zumindest mit sed) keine gute Antwort einfällt .

Ich habe eine große CSV-Datei (200+ GB) mit Zeilen, die wie folgt aussehen:

<alphanumerical_identifier>,<number>

wo <alphanumerical_identifier>ist über die gesamte Datei eindeutig. Ich möchte eine separate Datei erstellen, die die erste Spalte durch einen Index ersetzt , d. H.

<index>,<number>

damit wir bekommen:

1, <number>
2, <number>
3, <number>

Kann awkein zunehmender Index generiert werden, ohne die gesamte Datei in den Speicher zu laden?

Da der Index monoton ansteigt, ist es möglicherweise noch besser, den Index einfach fallen zu lassen. Wäre die Lösung dafür so anders?, Dh:

<number>
<number>
<number>
Amelio Vazquez-Reina
quelle
Ich bin mir nicht sicher, ob diese Lösung machbar ist. Aber wie wäre es, wenn Sie so viele Zahlen wie in der CSV-Datei in einer separaten Datei generieren und dann einfach die zweite Spalte der CSV-Datei an diese Datei anhängen?
Ramesh
@Ramesh Das ist vollkommen in Ordnung, solange die Ausgabe korrekt ist.
Amelio Vazquez-Reina
2
Ich vermute, ich verstehe etwas falsch; sonst awk -F, '{print ++n, $2}'würde funktionieren. Oder awk -F, '{print $2}'für die zweite Variante.
G-Man sagt "Reinstate Monica"
2
@ G-Man, das ist es wahrscheinlich, obwohl FNRes genauso gut dienen würde wie++n
iruvar
1
Ich würde dreimal prüfen, ob Sie diesen Uniq-Bezeichner wirklich entfernen können ... warum nicht eine erste (dritte) Spalte mit dem Index hinzufügen, aber den Bezeichner trotzdem behalten? Wird dieser Bezeichner nirgendwo anders verwendet?
Olivier Dulac

Antworten:

13

Nicht in der Nähe eines zu testenden Terminals, aber wie wäre es mit dem oft übersehenen nlBefehl? Etwas wie:

cut -f 2 -d , original.csv | nl -w 1 -p -s , > numbered.csv

Bischof
quelle
1
PS: Eine 200 GB CSV-Datei? Wow, und ich fand die Arbeit mit der nordamerikanischen Ported Number Database als CSV (ein paar DVDs) riesig!
Bischof
1
Es funktioniert, obwohl nach der Nummer ein großes Leerzeichen steht. Ich würde es ersetzen durch:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
Ángel
@Angel: Danke, meine Antwort wurde aktualisiert, um die Option width -w 1anstelle der Linksnummerierung zu verwenden .
Bischof
Danke @bishop - Wohin gehen die Eingabe- und Ausgabedateinamen?
Amelio Vazquez-Reina
1
@ user815423426 Ja, der cutBefehl vor dem Pipe-Symbol ( |) gibt Ihnen nur die zweite Spalte mit impliziten Zeilennummern.
Bischof
7

Hier sind ein paar Ansätze, aber keiner wird die Geschwindigkeit der Annäherung cutund nlLösung oben:

  1. awk

    awk -F, '{$1=NR;print $1","$2;}' file.csv > newfile.csv
  2. Perl

    perl -pe 's/[^,]+/$./' file.csv > newfile.csv

    oder

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (aber ich empfehle es nicht für eine 200G-Datei, es wird ewig dauern)

    i=1; while IFS=, read foo num; do 
            printf "%d,%s\n" $((i++)) $num; 
    done < file.csv > newfile.csv

Die obigen Lösungen sind nach Geschwindigkeit sortiert. Ich habe auf meinem Laptop und einer 40M-Datei getestet und sie haben (durchschnittlich 10 Läufe) 2,2282 (awk), 2,4555 (1. Perl), 3,1825s (2. Perl) und satte 48,6035s für die Shell benötigt. Die sehr clevere cutund bereits vorhandene nlLösung war mit 0,6078 Sekunden etwa viermal schneller.

terdon
quelle
Schön, danke für die Statistiken! Das Shell-Ergebnis überrascht mich etwas. Wenn Sie ersetzen printfmit echo, nicht verbessert das Timing deutlich?
Bischof
2
40G-Datei in 2,2282 Sekunden verarbeitet? Wo kann ich mir diesen Laptop besorgen?
John B
2
@ JohnB umm, ja, sorry, das war 40M, nicht G :)
terdon
Ich mag das Zurücksetzen des $1Ansatzes mit awk. Die cutLösung ist definitiv viel schneller, aber das ist zu erwarten, da sie durch <alphanumerical_identifier>nichts ersetzt wird. Ich denke, die schnellste awkVariante könnte so etwas sein wie : mawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv.
John B
@ JohnB ah, ja, ich würde vermuten, dass die Verwendung OFSanstelle des expliziten Druckens ,etwas schneller ist und dass dies zu einem signifikanten Unterschied bei großen Dateien führen kann.
Terdon