Reindicizzazione di un file CSV di grandi dimensioni


11

Ho esaminato le risposte in questo thread utile , ma il mio problema sembra essere abbastanza diverso da non riuscire a pensare a una buona risposta (almeno con sed).

Ho un file CSV di grandi dimensioni (oltre 200 GB) con righe simili alle seguenti:

<alphanumerical_identifier>,<number>

dove <alphanumerical_identifier>è univoco in tutto il file. Vorrei creare un file separato che sostituisca la prima colonna con un indice , ad es

<index>,<number>

in modo che otteniamo:

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

È possibile awkgenerare un indice crescente senza caricare l'intero file in memoria?

Poiché l'indice aumenta monotonicamente, potrebbe essere ancora meglio abbandonare l'indice. La soluzione sarebbe così diversa ?, ovvero:

<number>
<number>
<number>

Non sono sicuro della fattibilità di questa soluzione. Ma che ne dici di generare tanti numeri quanti nel file CSV in un file separato e poi aggiungere semplicemente la seconda colonna del file CSV a quel file?
Ramesh,

@Ramesh Va benissimo purché l'output sia corretto.
Amelio Vazquez-Reina,

2
Sospetto di aver frainteso qualcosa; altrimenti, awk -F, '{print ++n, $2}'funzionerebbe. O awk -F, '{print $2}'per la seconda variante.
G-Man dice 'Reinstate Monica' il

2
@G-Man, probabilmente è così anche se FNRservirebbe altrettanto bene++n
iruvar

1
Verificherei tre volte che puoi davvero sbarazzarti di quell'identificatore Uniq ... perché non aggiungere una prima (terza) colonna con l'indice, ma mantenere comunque l'identificatore? Non è che identificativo utilizzato in qualsiasi altra parte?
Olivier Dulac,

Risposte:


13

Non vicino a un terminale da testare, ma che ne dici del nlcomando spesso trascurato ? Qualcosa di simile a:

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


1
PS: un file CSV da 200 GB ? Wow, e ho pensato che lavorare con il Ported Number Database nordamericano come CSV (un paio di DVD) fosse enorme!
vescovo,

1
Funziona, anche se dopo il numero c'è un grande spazio vuoto. Vorrei sostituirlo con:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
Ángel,

@Angel: grazie, ho aggiornato la mia risposta per utilizzare l'opzione di larghezza -w 1anziché la numerazione a sinistra.
vescovo,

Grazie @bishop - Dove vanno i nomi dei file di input e output?
Amelio Vazquez-Reina,

1
@ user815423426 Sì, il cutcomando prima del simbolo pipe ( |) ti darà solo la seconda colonna, con effettivamente numeri di riga impliciti.
vescovo,

7

Ecco alcuni approcci, ma nessuno si avvicinerà alla velocità della soluzione cute nlsopra:

  1. awk

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

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

    o

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (ma non lo consiglio per un file 200G, ci vorranno anni)

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

Le soluzioni precedenti sono ordinate in ordine di velocità. Ho testato sul mio laptop e un file 40M e hanno preso (in media 10 corse) 2.2282 (awk), 2.4555 (1 ° perl), 3.1825s (2 ° perl) e un enorme 48.6035s per la shell. La soluzione molto intelligente cutche nlhai già è stata circa 4 volte più veloce a 0.6078s.


Bello, grazie per le statistiche! Il risultato del guscio mi sorprende, un po '. Se si sostituisce printfcon echo, i tempi migliorano significativamente?
vescovo,

2
File 40G elaborato in 2.2282 secondi? Dove posso trovare quel laptop?
Giovanni B,

2
@JohnB umm, sì, scusa, era 40M, non G :)
terdon

Mi piace il ripristino $1dell'approccio con awk. La cutsoluzione è decisamente molto più veloce, ma è prevedibile in quanto non sostituisce <alphanumerical_identifier>con nulla. Credo che il più veloce awkvariante potrebbe essere qualcosa del tipo: mawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv.
Giovanni B,

@JohnB ah, sì, immagino che l'utilizzo OFSanziché la stampa esplicita ,sarebbe leggermente più veloce e ciò potrebbe aggiungere una differenza significativa in file di grandi dimensioni.
terdon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.