arquivo CSV + definir parâmetros e valores CSV no script bash

1

Eu tenho o seguinte arquivo CSV:

Alabama,Alaska,Arizona,Arkansas,California,Colorado,Connecticut,Delaware,Florida,Georgia,Hawaii,Idaho,Illinois,Indiana,Iowa
1000,"1 0 0 1",1002,1002,1003,1004,1005,"1 0 0 6",1007,1008,1009,1010,1011,1012,1013
100,101,102,102,103,104,105,"1 0 6 2",107,108,109,110,111,112,113
10001,10011,10021,10021,10031,10041,10051,10061,10071,10081,10091,10101,10111,10121,10131
.
.
.
.

Minha meta é definir os parâmetros CSV (todos os estados em CSV) com seus valores no meu script bash

por exemplo

#!/bin/bash

Alabama=1000
.
.
.
Iowa=1013

então no meu script bash eu posso ler cada parâmetro

exemplo

 echo $Alabama
 1000

Primeiro, tentei escrever o código (errado) a seguir, para definir os parâmetros com seus valores:

#!/bin/bash

counter=1

for CSV_COLUMN in Alabama  Alaska  Arizona Arkansas  California  Colorado  Connecticut Delaware Florida  Georgia  Hawaii  Idaho  Illinois  Indiana  Iowa 
do
  export $CSV_COLUMN=' echo $CSV_LINE | cut -d',' -f$counter '
  counter=$counter+1
done

O teste deve ser (do script bash)

echo $Alabama
1000

Como devo alterar meu código para implementar minha ideia?

    
por maihabunash 15.07.2014 / 15:14

2 respostas

2

O comando

awk -F, 'NR==1 { for (i=1; i<=NF; i++) sn[i]=$i }
         NR==2 { for (i=1; i<=NF; i++) print sn[i] "=" $i; exit }' states

onde states é o seu arquivo, será exibido

Alabama=1000
Alaska="1 0 0 1"
Arizona=1002
Arkansas=1002
California=1003
Colorado=1004
Connecticut=1005
Delaware="1 0 0 6"
Florida=1007
Georgia=1008
Hawaii=1009
Idaho=1010
Illinois=1011
Indiana=1012
Iowa=1013
  • O separador de campos -F, sets awk para , .
  • NR==1 significa “faça o seguinte apenas no primeiro registro (linha)”; NR==2 significa a segunda linha.
  • O (primeiro) for de loop examina cada campo na primeira linha e atribui os valores (nomes de estado) à sn array: sn[1]=Alabama , sn[2]=Alaska ,…).
  • O segundo loop for examina cada campo (delimitado por vírgula) na segunda linha e o associa ao nome do estado correspondente (da primeira linha) e a = , como mostrado acima.
  • Então, exit , então awk não precisa ler o restante do arquivo.

Então

eval $(awk -F, 'NR==1 { for (i=1; i<=NF; i++) sn[i]=$i }
                NR==2 { for (i=1; i<=NF; i++) print sn[i] "=" $i; exit }' states)

irá capturar essa saída e interpretá-la como uma série de comandos. Feito.

Se você está determinado a usar um loop de shell e o comando cut , considere

values=$(sed -n '2p;2q' states)
counter=1
for state_name in $(sed 's/,/ /g;1q' states)
do
    eval $state_name=$(echo "$values" | cut -d, -f$counter)
    counter=$((counter+1))
done

Ou você poderia listar os nomes de estado explicitamente, como você fez em seu exemplo / tentativa (%código%). Mas por que você deseja duplicar seus dados em seu código quando ele já está no arquivo? E você poderia eliminar a variável for var in Alabama Alaska Arizona Arkansas … e fazer

eval $state_name=$(sed -n '2p;2q' states | cut -d, -f$counter)

no loop, mas isso exigiria ler o arquivo values 50 vezes em vez de uma vez. (Ou 51 vezes em vez de duas vezes, se você contar a declaração states .

    
por 15.07.2014 / 19:48
1

Use esta linha:

read 'sed -e 's/,/ /g' -e '1q;d' file' < <(sed -e 's/\ /\\ /g' -e 's/"//g' -e 's/,/ /g' -e '2q;d' file)

Explicação :

  • O primeiro comando sed faz com que apenas a primeira linha do arquivo seja impressa e as vírgulas ( , ) sejam substituídas por espaços: Alabama Alaska Arizona Arkansas California ...

  • O segundo comando sed faz o mesmo com a segunda linha (parece na sua pergunta que você quer apenas os valores da segunda linha): 1000 1001 1002 1002 ... .

  • read -r atribui a primeira lista à segunda.

Depois de testar os valores com echo :

echo $Alabama
1000
echo $Alaska
1 0 0 1
echo $Georgia
1008
    
por 15.07.2014 / 16:30

Tags