Filtre un archivo .CSV basado en los valores de la quinta columna de un archivo e imprima esos registros en un nuevo archivo

16

Tengo un archivo .CSV con el siguiente formato:

"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 columna del archivo tiene diferentes cadenas. Necesito filtrar el archivo según el valor de la quinta columna. Digamos que necesito un nuevo archivo del archivo actual que tiene registros solo con el valor "cadena 1" en su quinto campo.

Para esto probé el siguiente comando,

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

pero me estaba arrojando un error de la siguiente manera:

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

Luego usé lo siguiente que me da una salida extraña.

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

Salida:

"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" ""

PD: Utilicé el comando toupper para estar en el lado seguro, ya que no estoy seguro de si la cadena estará en mayúsculas o minúsculas. Necesito saber qué está mal con mi código y si el espacio en la cadena importa mientras busco un patrón usando AWK.

Dhruuv
fuente

Respuestas:

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

Salida

"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",""

Creo que esto es lo que quieres.

limovala
fuente
El resultado es exactamente como lo necesitaba. No he pensado en hacer '","'delimitador, de lo contrario habría resuelto mi problema ... gran solución ...
Dhruuv
@Dhruuv haciendo '","'el delimitador es lo que la mayoría de las respuestas a su pregunta anterior sugirió :).
terdon
@terdon: sí, lo sé, pero eso no se me ocurrió cuando tenía el problema. Francamente, pensé que podría ser algo con el comando o algo más que los delimitadores que causaban el problema ... :) Por lo tanto, no lo intenté ... :(
Dhruuv
2
@Dhruuv no está seguro de los detalles, ya que no puedo decir lo que está tratando de hacer, pero su condición es casi seguro que está mal. ¿Estás intentando imprimir solo si $ 5 es HYPERION? Si es así, inténtalo else{if(toupper($5)=="HYPERION"){print}}. No en mi computadora en este momento, por lo que podría tener la sintaxis incorrecta, pero no puede dar una condición a una instrucción else.
terdon
1
awk -F '","' 'BEGIN {OFS=","} { if (NR==1) {print} else{if (toupper($5) == "STRING 1") print} }' file1
limovala 01 de
2

El problema con CSV es que no hay un estándar. Si necesita lidiar con datos con formato CSV con frecuencia, es posible que desee buscar un método más robusto en lugar de simplemente usarlo ","como su separador de campo. En este caso, los Text::CSVmódulos CPAN de Perl son excepcionalmente adecuados para el trabajo:

$ 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",""

fuente
-1
awk 'BEGIN {FS = "," }'  '{ (if toupper($5)  == "STRING 1") print; }'  file1.csv > file2.csv
Golfo pérsico
fuente
Lamento decirlo, pero su solución no devuelve ningún registro del archivo ... Creo que simplemente agregue el delimitador como '","'lo hará ... gracias ... :)
Dhruuv
@Mohsen -1 porque 1) necesita escapar del "o no se entienden como partes del delimitador de archivos. Vea las respuestas a la otra pregunta del OP y 2) está separando el bloque BEGIN del resto del comando que completamente lo rompe. Intente awk 'BEGIN {FS = "," }' '{print $0}', verá que no produce ningún resultado. En el futuro, pruebe sus respuestas para ver si realmente funcionan antes de publicarlas.
terdon