Mais elegante iterando várias matrizes bash em paralelo

1

Estou trabalhando em um script que mastiga alguns dados que sugam de um arquivo CSV. Eu já li os dados em vários arrays (um para cada coluna no arquivo); Agora preciso trabalhar com todos os dados em sequência.

Atualmente, estou fazendo isso:

# Read in the data:
declare -a DATACOL1 DATACOL2 RAWDATA
RAWDATA=($( sed '1d' /path/to/data.csv )) # Remove the header line
for line in ${RAWDATA[@]}; do
   declare -a LINEDATA LINE
   LINE=$( echo "$line" | sed 's/,/ /g' )
   for field in LINE; do
       LINEDATA+=("${field}")
   done
   DATACOL1+=(${LINEDATA[0]})
   DATACOL2+=(${LINEDATA[1]})
done


# Work on the data:
for i in $( seq 0 $[${#DATACOL1[@]}-1}; do
   stuff and things with ${DATACOL1[i]} and ${DATACOL2[i]}
done

Minhas perguntas (possivelmente relacionadas entre si) são duplas:

  • Existe uma maneira mais elegante de trabalhar posteriormente nos dados do que for i in $( seq 0 $[${#DATACOL1[@]}-1} para iterar sobre eles? Funciona, mas é feio.

  • Existe uma maneira mais elegante de absorver os dados CSV?

Isso é no bash 3, então eu não tenho arrays associativos.

    
por DopeGhoti 17.11.2015 / 20:01

1 resposta

4

Eu escreveria:

mapfile -t rawdata < <(sed 1d /path/to/data.csv)
datacol1=()
datacol2=()

for line in "${rawdata[@]}"; do
    IFS=, read -ra fields <<< "$line"
    datacol1+=( "${fields[0]}" )
    datacol2+=( "${fields[1]}" )
done

for ((i=0; i < "${#datacol1[@]}"; i++)); do
    stuff with "${datacol1[i]}" and "${datacol2[i]}"
done
  • use mapfile para ler as linhas de um arquivo em uma matriz
  • use IFS e read para ler campos separados por vírgulas de uma linha
    • quebrará com qualquer vírgula dentro de strings entre aspas: use um analisador CSV real .
  • use o formulário em forma de C de for para evitar chamar para seq

Claro, você não precisa do segundo loop ou das variáveis datacol *

for line in "${rawdata[@]}"; do
    IFS=, read -a fields <<< "$line"
    stuff with "${fields[0]}" and "${fields[1]}"
done

No bash 3 você não terá mapfile , então use um while-loop

datacol1=()
datacol2=()
while IFS=, read -ra fields; do
    datacol1+=("${fields[0]}")
    datacol2+=("${fields[1]}")
done < <(sed 1d /path/to/data.csv)
    
por 17.11.2015 / 20:35