2013-01-19 17 views
9

C'è un modo per utilizzare bash per rimuovere le ultime quattro colonne per alcuni file CSV di input? Le ultime quattro colonne possono avere campi di lunghezza variabile da linea a linea, quindi non è sufficiente cancellare solo un certo numero di caratteri dalla fine di ogni riga.metodo bash per rimuovere le ultime 4 colonne dal file csv

risposta

12

Taglia può farlo se tutte le linee hanno lo stesso numero di campi o awk se non lo fai.

cut -d, -f1-6 # assuming 10 fields 

stamperà i primi 6 campi, se si desidera controllare l'utilizzo di uscita seperater --output-delimitatore = stringa

awk -F , -v OFS=, '{ for (i=1;i<=NF-4;i++){ printf $i, }; printf "\n"}' 

Loops su campi fino a th numero di campi -4 e stampe fuori.

+0

nella riga di awk, suppongo che tu voglia printf $ non stampare $ i, giusto? errore di battitura forse? e 'print $ i,' non funzionerà, potresti voler avere ';' un altro errore di battitura? – Kent

+0

@kent yeah significava printf $ i, non è necessario avere il; se solo un comando. – peteches

+0

hai ragione, ma hai "virgola" .. :) – Kent

6

È possibile utilizzare cut per questo se si conosce il numero di colonne. Ad esempio, se il file ha 9 colonne, e la virgola è il vostro delimitatore:

cut -d',' -f -5 

Tuttavia, questo assume i dati nel file CSV non contiene virgole. cut interpreterà le virgole anche all'interno delle virgolette come delimitatori.

1

awk one-liner:

awk -F, '{for(i=0;++i<=NF-5;)printf $i", ";print $(NF-4)}' file.csv 

il vantaggio di utilizzare awk sopra taglio è, non c'è bisogno di contare quante colonne avete e quante colonne si desidera conservare. Dal momento che quello che vuoi è rimuovere le ultime 4 colonne.

vedere il test:

kent$ seq 40|xargs -n10|sed 's/ /, /g'   
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 
11, 12, 13, 14, 15, 16, 17, 18, 19, 20 
21, 22, 23, 24, 25, 26, 27, 28, 29, 30 
31, 32, 33, 34, 35, 36, 37, 38, 39, 40 

kent$ seq 40|xargs -n10|sed 's/ /, /g' |awk -F, '{for(i=0;++i<=NF-5;)printf $i", ";print $(NF-4)}' 
1, 2, 3, 4, 5, 6 
11, 12, 13, 14, 15, 16 
21, 22, 23, 24, 25, 26 
31, 32, 33, 34, 35, 36 
1

Questo potrebbe funzionare per voi (GNU sed):

sed -r 's/(,[^,]*){4}$//' file 
+0

Nel mio senso, è la migliore risposta qui! –

10
cat data.csv | rev | cut -d, -f-5 | rev 

rev inverte le linee, in modo che non importa se tutte le righe avere lo stesso numero di colonne, rimuoverà sempre l'ultimo 4. Funziona solo se le ultime 4 colonne non contengono le virgole stesse.

+2

Questa è una soluzione davvero bella a mio avviso, +1 per l'uso di rev (non sapevo che esistesse) – skd

1

Questa soluzione awk in modo compromessi

awk -F, 'OFS=","{for(i=NF; i>=NF-4; --i) {$i=""}}{gsub(",,,,,","",$0);print $0}' temp.txt 
3
awk -F, '{NF-=4; OFS=","; print}' file.csv 

oppure

awk -F, -vOFS=, '{NF-=4;print}' file.csv 

cadrà ultime 4 colonne da ogni riga.

+0

Un buon modo per rilasciare le colonne extra, ma per me questo sostituisce le virgole tra le colonne con gli spazi nell'output . C'è un modo semplice per evitarlo e tenerli come virgole? –

+0

È possibile aggiungere nuovamente il delimitatore con awk -F, '{NF- = 4; OFS = ""; print} ' –

+0

Ottimo, funziona per me. Inoltre, è possibile impostare 'OFS' in un blocco' BEGIN' o con l'argomento '-v' della riga di comando come' awk -F, -vOFS =, ... ' –

Problemi correlati