Ignorar el delimitador presente dentro de las comillas

Tengo un file .csv la siguiente manera:

 "ID0054XX","PT. SUMUT","18 JL.BONJOL","SUMATERA UTARA, NORTH","MEDAN","","ID9856","PDSUIDSAXXX","","","","Y" "ID00037687","PAN INDONESIA, PT.","JALAN JENDERAL, SUDIRMAN, SENAYAN","","INDIA","","ID566543","PINBIDJAXXX","","0601","","Y" 

Tengo un script que asigna cada uno de los valores separados por comas a una variable única usando , como el delimitador.

La porción de la secuencia de commands es la siguiente:

 IFS=, [ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; } while read Key Name Address1 Address2 City State Country SwiftCode Nid Chips Aba IsSwitching do echo "-------------------------------------------------------------------" echo "From Key : $Key" echo "-------------------------------------------------------------------" echo "-------------------------------------------------------------------" echo "From Name : $Name" 

Lo que hace es separar los valores que tienen coma dentro de las comillas contra mi resultado deseado de separar de forma única cada valor a sus respectivas variables.

Intenté replace la coma como IFS=[","] pero no tuve suerte. Cualquier sugerencia / ayuda es realmente apreciada.

Estás haciendo un par de cosas mal aquí:

  1. Estás usando el intérprete de commands para analizar el text.

    Si bien esto es posible, es muy ineficiente. Es lento, difícil de escribir, difícil de leer y muy difícil de hacer correctamente. El caparazón no está diseñado para este tipo de cosas.

  2. Está intentando analizar un file csv sin un analizador csv.

    CSV no es un formatting simple. Puede tener campos que contengan el delimitador como lo hace aquí. También puede tener campos que abarcan múltiples líneas. Intentar analizar datos CSV arbitrarios con una simple coincidencia de patrones es muy, muy complicado y extremadamente difícil de conseguir.

La solución mala y hacky es hacer algo como esto:

 $ sed 's/","/"|"/g' file.csv | while IFS='|' read -r Key Name Address1 Address2 City \ State Country SwiftCode Nid Chips Aba IsSwitching; do echo "From Key : $Key"; echo "From Name : $Name"; done From Key : "ID0054XX" From Name : "PT. SUMUT" From Key : "ID00037687" From Name : "PAN INDONESIA, PT." 

Eso replaceá todo "," con "|" y luego usa | como el delimitador Por supuesto, eso no funcionará si alguno de tus campos puede contener | .

El enfoque bueno y limpio es usar un lenguaje de scripting adecuado, no el shell, y un analizador csv. Por ejemplo, en Perl 1 :

 $ cat file.csv | perl -MText::CSV -le ' $csv = Text::CSV->new({binary=>1}); while ($row = $csv->getline(STDIN)){ my ($Key, $Name, $Address1, $Address2, $City, $State, $Country, $SwiftCode, $Nid, $Chips, $Aba, $IsSwitching) = @$row; print "From Key: $Key\nFrom Name: $Name";}' From Key: ID0054XX From Name: PT. SUMUT From Key: ID00037687 From Name: PAN INDONESIA, PT. 

O, como un guión:

 #!/usr/bin/perl -l use strict; use warnings; use Text::CSV; open(my $fh, "file.csv"); my $csv = Text::CSV->new({binary=>1}); while (my $row = $csv->getline($fh)){ my ( $Key, $Name, $Address1, $Address2, $City, $State, $Country, $SwiftCode, $Nid, $Chips, $Aba, $IsSwitching ) = @$row; print "From Key: $Key\nFrom Name: $Name"; } 

Tenga en count que primero tendrá que instalar el module Text::CSV ( cpanm Text::CSV ) y es posible que desee instalar cpanm (package cpanminus en la mayoría de las distribuciones)

Alternativamente, en Python 3:

 #!/usr/bin/env python3 import csv with open('file.csv', newline='') as csvfile: linereader = csv.reader(csvfile, delimiter=',', quotechar='"') for row in linereader: print("From Key: %s\nFrom Name: %s" % (row[0], row[1])) 

Guarde el código Python anterior como script y ejecútelo en su file:

 $ foo.py From Key: ID0054XX From Name: PT. SUMUT From Key: ID00037687 From Name: PAN INDONESIA, PT. 

1 Sí, soy consciente de que es una UUoC, pero es más sencillo escribir de esta manera.