Filtra un file .CSV in base ai valori della quinta colonna di un file e stampa quei record in un nuovo file


16

Ho un file .CSV con il formato seguente:

"column 1","column 2","column 3","column 4","column 5","column 6","column 7","column 8","column 9","column 10
"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23455","12312255564","string, with, multiple, commas","string with or, without commas","string 2","USD","433","70%","07/15/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""
"46476","15467534544","lengthy string, with commas, multiple: colans","string with or, without commas","string 2","CAND","388","70%","09/21/2013",""

La quinta colonna del file ha stringhe diverse. Devo filtrare il file in base al valore della 5a colonna. Diciamo, ho bisogno di un nuovo file dal file corrente che ha record solo con il valore "stringa 1" nel suo quinto campo.

Per questo ho provato il comando seguente,

awk -F"," ' { if toupper($5) == "STRING 1") PRINT }' file1.csv > file2.csv

ma mi stava lanciando un errore come segue:

awk: { if toupper($5) == "STRING 1") PRINT }
awk: ^ syntax error
awk: { if toupper($5) == "STRING 1") PRINT }
awk: ^ syntax error

Ho quindi usato quanto segue che mi dà un output dispari.

awk -F"," '$5="string 1" {print}' file1.csv > file2.csv

Produzione:

"column 1" "column 2" "column 3" "column 4" string 1 "column 6" "column 7" "column 8" "column 9" "column 10
"12310" "42324564756" "a simple string with a comma" string 1 without commas" "string 1" "USD" "12" "70%" "08/01/2013" ""
"23455" "12312255564" "string with string 1 commas" "string with or without commas" "string 2" "USD" "433" "70%" "07/15/2013" ""
"23525" "74535243123" "string with commas string 1 "string with or without commas" "string 1" "CAND" "744" "70%" "05/06/2013" ""
"46476" "15467534544" "lengthy string with commas string 1 "string with or without commas" "string 2" "CAND" "388" "70%" "09/21/2013" ""

PS: ho usato il comando toupper per essere al sicuro, poiché non sono sicuro che la stringa sia in minuscolo o maiuscolo. Devo sapere cosa c'è che non va nel mio codice e se lo spazio nella stringa è importante durante la ricerca di un modello usando AWK.

Risposte:


17
awk -F '","'  'BEGIN {OFS=","} { if (toupper($5) == "STRING 1")  print }' file1.csv > file2.csv 

Produzione

"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""

Penso che questo sia quello che vuoi.


L'output è esattamente come ne avevo bisogno. Non ho pensato di fare '","'delimitatore, altrimenti avrebbe risolto il mio problema ... ottima soluzione ...
Dhruuv,

@Dhruuv fare '","'il delimitatore è ciò che la maggior parte delle risposte alla tua domanda precedente ha suggerito :).
terdon

@terdon: sì, lo so, ma non mi è venuto in mente quando stavo avendo il problema. Francamente, ho pensato che potrebbe essere qualcosa con il comando o qualcosa di diverso dai delimitatori che stava causando il problema ... :) Quindi non ci ho provato ... :(
Dhruuv

2
@Dhruuv non sono sicuro dei dettagli poiché non posso dire cosa stai cercando di fare, ma la tua condizione di altro è quasi certamente sbagliata. Stai cercando di stampare se $ 5 è HYPERION? Se è così, prova else{if(toupper($5)=="HYPERION"){print}}. Al momento non sul mio computer, quindi potrei avere la sintassi sbagliata, ma non puoi dare una condizione a un'altra istruzione.
terdon

1
awk -F '","' 'BEGIN {OFS=","} { if (NR==1) {print} else{if (toupper($5) == "STRING 1") print} }' file1
limovala,

2

Il problema con CSV è che non esiste uno standard. Se hai bisogno di gestire spesso dati in formato CSV, potresti voler esaminare un metodo più solido piuttosto che utilizzarlo ","come separatore di campo. In questo caso, i Text::CSVmoduli CPAN di Perl sono eccezionalmente adatti al lavoro:

$ perl -mText::CSV_XS -WlanE '
    BEGIN {our $csv = Text::CSV_XS->new;} 
    $csv->parse($_); 
    my @fields = $csv->fields(); 
    print if $fields[4] =~ /string 1/i;
' file1.csv
"12310","42324564756","a simple string with a , comma","string with or, without commas","string 1","USD","12","70%","08/01/2013",""
"23525","74535243123","string , with commas, and - hypens and: semicolans","string with or, without commas","string 1","CAND","744","70%","05/06/2013",""

-1
awk 'BEGIN {FS = "," }'  '{ (if toupper($5)  == "STRING 1") print; }'  file1.csv > file2.csv

Mi dispiace dirlo, ma la tua soluzione non restituisce alcun record dal file ... Penso solo aggiungendo il delimitatore come '","'farà ... grazie ... :)
Dhruuv

@Mohsen -1 perché 1) devi scappare da "o non sono compresi come parti del delimitatore di file. Vedi le risposte all'altra domanda del PO e 2) stai separando il blocco BEGIN dal resto del comando che completamente lo interrompe. Prova awk 'BEGIN {FS = "," }' '{print $0}', vedrai che non produce alcun output. In futuro, verifica le risposte per vedere se funzionano davvero prima di pubblicarle.
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.