cria variáveis de CSV com vários números de campos

0

Procurando por ajuda para transformar um CSV em variáveis. Eu tentei usar o IFS, mas parece que você precisa definir o número de campos. Eu preciso de algo que possa lidar com um número variável de campos.

* Estou modificando minha pergunta original com o código atual que estou usando (tirado da resposta fornecida pelo hschou) que inclui nomes de variáveis atualizados usando tipo em vez de linha, seção etc.

Tenho certeza que você pode dizer pelo meu código, mas eu sou bastante verde com scripts, então estou procurando ajuda para determinar se e como devo adicionar outro loop ou ter uma abordagem diferente para analisar os dados typeC porque, embora eles seguem o mesmo formato, há apenas uma entrada para cada um dos dados typeA e typeB, e pode haver entre 1-15 entradas para os dados typeC. O objetivo é apenas 3 arquivos, um para cada um dos tipos de dados.

Formato de dados:

Recipiente: PL [1-100]
TypeA: [1-20]. [1-100]. [1-1000]. [1-100] - [1-100]
TypeB: [1-20]. [1-100]. [1-1000]. [1-100] - [1-100]
TypeC (1 a 15 entradas): [1-20]. [1-100]. [1-1000]. [1-100] - [1-100]

* Não há cabeçalho no CSV, mas se houvesse, ficaria assim (os dados de Container, typeA e typeB sempre estão na posição 1,2,3 e os dados typeC são todos os que seguem): Container, typeA, typeB, typeC, tycpeC, typeC, typeC, typeC, ..

CSV: PL3, 12, 14, 57, 77, 77, PL4,12.1.4.5-78,13.6.4.5-21,17.3.577.9-30,17.3.779.12-34 PL5,12.1.4.5-79,13.6.4.5-22,17.3.577.9-31,17.3.779.12-35,17.3.802.12-62,17.3.917.12-47 PL6,12.1.4.5-80,13.6.4.5-23,17.3.577.9-32,17.3.779.12-36,17.3.802.12-63,17.3.917.12-48,17.3.956.12-66 PL7,12.1.4.5-81,13.6.4.5-24,17.3.577.9-33,17.3.779.12-37,17.3.802.12-64,17.3.917.12-49,17.3.956.12-67,17.3.993.12-46 PL8,12.1.4.5-82,13.6.4.5-25,17.3.577.9-34

Código:

#!/bin/bash
#Set input file
_input="input.csv"
#  Pull variables in from csv
# read file using while loop
while read; do
    declare -a COL=( ${REPLY//,/ } )
    echo -e "containerID=${COL[0]}\ntypeA=${COL[1]}\ntypeB=${COL[2]}" >/tmp/typelist.txt
    idx=1
    while [ $idx -lt 10 ]; do
        echo "typeC$idx=${COL[$((idx+2))]}" >>/tmp/typelist.txt
        let idx=idx+1
#whack off empty variables
sed '/\=$/d' /tmp/typelist.txt > /tmp/typelist2.txt && mv /tmp/typelist2.txt /tmp/typelist.txt
#set variables from temp file
. /tmp/typelist.txt
done
sleep 1

#Parse data in this loop.#
echo -e "\n"
echo "Begin Processing for $container"
#echo $typeA
#echo $typeB
#echo $typeC
#echo -e "\n"

#Strip - from sub data for extra parsing  
typeAsub="$(echo "$typeA" | sed 's/\-.*$//')"
typeBsub="$(echo "$typeB" | sed 's/\-.*$//')"
typeCsub1="$(echo "$typeC1" | sed 's/\-.*$//')"

#strip out first two decimils for extra parsing
typeAprefix="$(echo "$typeA" | cut -d "." -f1-2)"
typeBprefix="$(echo "$typeB" | cut -d "." -f1-2)"
typeCprefix1="$(echo "$typeC1" | cut -d "." -f1-2)"

#echo $typeAsub
#echo $typeBsub
#echo $typeCsub1
#echo -e "\n"

#echo $typeAprefix
#echo $typeBprefix
#echo $typeCprefix1
#echo -e "\n"

echo "Getting typeA dataset for $typeA"
#call api script to pull data ; echo out for test
echo "API-gather -option -b "$typeAsub" -g all > "$container"typeA-dataset"
sleep 1  


echo "Getting typeB dataset for $typeB"
#call api script to pull data ; echo out for test
echo "API-gather -option -b "$typeBsub" -g all > "$container"typeB-dataset"
sleep 1  

echo "Getting typeC dataset for $typeC1"
#call api script to pull data ; echo out for test
echo "API-gather -option -b "$typeCsub" -g all > "$container"typeC-dataset"
sleep 1  

echo "Getting additional typeC datasets for $typeC2-15"
#call api script to pull data ; echo out for test
echo "API-gather -option -b "$typeCsub2-15" -g all >> "$container"typeC-dataset"
sleep 1  

echo -e "\n"
done < "$_input"

exit 0

A velocidade não é uma preocupação, mas se eu fiz algo realmente estúpido lá, sinta-se livre para me bater na direção certa. :)

    
por Jdubyas 12.07.2017 / 07:09

3 respostas

0

Neste script, a linha é apenas lida na variável padrão $REPLY . Em seguida, substitua a vírgula com espaço ${REPLY//,/ } e coloque em uma matriz declare -a COL=() . A parte da seção é então tratada com um loop no qual o índice da coluna é calculado com $((idx+2)) :

#! /bin/bash
while read; do
    declare -a COL=( ${REPLY//,/ } )
    echo -e "container=${COL[0]}\nrow=${COL[1]}\nshelf=${COL[2]}"
    idx=1
    while [ $idx -lt 10 ]; do
        echo "section$idx=${COL[$((idx+2))]}"
        let idx=idx+1
    done
done
    
por 12.07.2017 / 08:31
0

Eu usaria um array associativo por registro csv: assumindo que seus dados estavam em um arquivo chamado input.csv

#!/usr/bin/env bash

counter=1          # provides index for each csv record
while read 
do
    IFS=',' a=( $REPLY )               # numeric array containing current row
    eval "declare -A row$counter"      # declare an assoc. array representing
                                       # this row   

    eval "row$counter+=( ['row']=${a[0]} )"
    a=( "${a[@]:1}" )
    eval "row$counter+=( ['shelf']=${a[0]} )"
    a=( "${a[@]:1}" )
    eval "row$counter+=( ['section1']=${a[0]} )"
    a=( "${a[@]:1}" )
    eval "row$counter+=( ['section2']=${a[0]} )"
    a=( "${a[@]:1}" )
    eval "row$counter+=( ['section3']=${a[0]} )"
    a=( "${a[@]:1}" )
    eval "row$counter+=( ['section4']=${a[0]} )"
    a=( "${a[@]:1}" )
    eval "row$counter+=( ['section5']=${a[0]} )"
    a=( "${a[@]:1}" )
    eval "row$counter+=( ['section6']=${a[0]} )"
    a=( "${a[@]:1}" )

    declare -p row$counter

    (( counter = counter + 1 ))
done < <( cat input.csv )

# access arbitrary element
printf "\n---------\n%s\n" ${row3["section4"]}

isso me dá uma saída como:

declare -A row1='([section6]="6" [section5]="5" [section4]="4" [section3]="4" [section2]="2" [section1]="1" [shelf]="12" [row]="PL3" )'
declare -A row2='([section6]="" [section5]="" [section4]="" [section3]="2" [section2]="1" [section1]="4" [shelf]="13" [row]="PL4" )'
declare -A row3='([section6]="" [section5]="" [section4]="3" [section3]="2" [section2]="1" [section1]="5" [shelf]="14" [row]="PL5" )'
declare -A row4='([section6]="5" [section5]="4" [section4]="3" [section3]="2" [section2]="1" [section1]="6" [shelf]="15" [row]="PL6" )'
declare -A row5='([section6]="5" [section5]="4" [section4]="3" [section3]="2" [section2]="1" [section1]="7" [shelf]="16" [row]="PL7" )'
declare -A row6='([section6]="5" [section5]="4" [section4]="3" [section3]="2" [section2]="1" [section1]="8" [shelf]="15" [row]="PL8" )'
declare -A row7='([section6]="5" [section5]="4" [section4]="3" [section3]="2" [section2]="1" [section1]="7" [shelf]="16" [row]="PL9" )'

---------
3
    
por 12.07.2017 / 08:46
0

Eu começaria com isso:

while IFS=, read -ra fields; do
    for (( i = ${#fields[@]} - 1; i >= 0; i-- )); do
        [[ -z "${fields[i]}" ]] && unset fields[i] || break
    done
    declare -p fields
done < file
declare -a fields='([0]="PL3" [1]="12" [2]="3" [3]="1" [4]="2" [5]="3" [6]="4" [7]="5" [8]="6")'
declare -a fields='([0]="PL4" [1]="13" [2]="4" [3]="1" [4]="2")'
declare -a fields='([0]="PL5" [1]="14" [2]="5" [3]="1" [4]="2" [5]="3")'
declare -a fields='([0]="PL6" [1]="15" [2]="6" [3]="1" [4]="2" [5]="3" [6]="4" [7]="5" [8]="6" [9]="7" [10]="8")'
declare -a fields='([0]="PL7" [1]="16" [2]="7" [3]="1" [4]="2" [5]="3" [6]="4" [7]="5" [8]="6" [9]="7" [10]="8" [11]="9")'
declare -a fields='([0]="PL8" [1]="15" [2]="8" [3]="1" [4]="2" [5]="3" [6]="4" [7]="5" [8]="6" [9]="7" [10]="8")'
declare -a fields='([0]="PL9" [1]="16" [2]="7" [3]="1" [4]="2" [5]="3" [6]="4" [7]="5" [8]="6" [9]="7" [10]="8" [11]="9")'

Verifique se você não tem nenhum espaço em branco no seu arquivo.

Eu questiono sua necessidade de ter numericamente nomes variáveis de incremento. Parece que você precisa de arrays bidimensionais, que é uma estrutura de dados que o bash não possui. Tem certeza de que o bash é a ferramenta certa para o trabalho?

    
por 13.07.2017 / 12:24