shell-script-pt
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [shell-script-pt] Fazendo um "de / para" com um cabeçalho CSV


From: T.Collons
Subject: Re: [shell-script-pt] Fazendo um "de / para" com um cabeçalho CSV
Date: Sat, 31 Jul 2021 18:43:52 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.11.0

Hola George


Perdona por responder en castellano, pero si lo hago en brasilero aun entenderás menos.


Creo que deberías tomar el camino que te indica el maestro Julio y usar comandos mas simples de BASH para eliminar campos vacíos.

Si abres el fichero .csv desde un edito de texto como GEDIT veras que todos los campos están separado por comas (,) o por el delimitador elegido en el momento de crearlo, si un campo ha quedado vació veras dos o mas comas (,) una detrás de otra según cuantos campos estén vacíos.

Así que solo te queda hacer un bucle que asigne a tu array datatypes [xxxx]="string" lo que haya en esa posición independientemente si contiene datos o esta vacía, solo teniendo en cuenta la posición de la coma(,).

Otra opción que se me ocurre es que si al recorrer el fichero .csv encuentras dos comas (,) juntas; usando sed le añadas un espacio sed 's/\,\,/\,\ \,/' y así nunca tendrás un campo vació.





El 31/7/21 a les 2:25, Julio C. Neves ha escrit:
George, hj é 6ª feira de noite e estou com a cabeça cansada demais para entender o que vc fez, mas me parece que a coisa é mais simples:
Cabec=$(sed '1!d; s/,/ /g' Arq.csv)
while IFS=, read $Cabec
do
    ... Aqui os dados lidos estarão nas variáveis com os nomes dos cabeçalhos...
done < <(tail -n +2 Arq.csv)

Um pequeno teste:
$ cat Arq.csv
C1,C2,C3
1,2,3
A,B,C
a,b,c
$ Cabec=$(sed '1!d; s/,/ /g' Arq.csv)
$ while IFS=, read $Cabec
do
    echo C1=$C1 -- C2=$C2 -- C3=$C3
done < <(tail -n +2 Arq.csv)
C1=1 -- C2=2 -- C3=3
C1=A -- C2=B -- C3=C
C1=a -- C2=b -- C3=c

Será que isso resolve ou simplifica sua lógica?
Um curso de Introdução ao Shell gratuito em: https://www.dicas-l.com.br/educacao/introducao-ao-shell-linux/
» Não tem tempo para fazer um curso presencial?
» Na sua cidade não tem nenhum bom curso de Linux?

Também damos treinamento em sua empresa
em qualquer cidadecom certificado e nota fiscal.








Em sex., 30 de jul. de 2021 às 20:14, George Robinson <george.robinson.br@gmail.com> escreveu:
Prezados colegas de lista:

Percebi que precisava ir mais a fundo no conceito de arrays associativos para não perguntar sem ter base para tal.

Fiz algum trabalho de leitura e consegui escrever o seguinte código:

#!/bin/bash
filecsv="myfile.csv"

# Declara Fields
declare -A Fields
Fields=(
    [fname]='First name.string\(\),'
    [mname]='Middle name.string\(\),'
    [lname]='Last name.string\(\),'
    [address]='Address.string\(\),'
    [address2]='Address2.string\(\),'
    [CITY]='City.string\(\),'
    [ST]='state.string\(\),'
    [ZIP]='zip.string\(\),'
    [SEQ_NUM]='seq_num.int64\(\),'
    [CREDIT_DAT]='credit_dat.string\(\),'
    [MAIL_DATE]='mail_date.string\(\),'
    [MAIL_CLASS]='mail_class.string\(\),'
    [EXP_DATE]='exp_date.string\(\),'
    [INHOME_DATE]='inhome_date.string\(\),'
    [lasercode]='lasercode.string\(\),'
    [BATCH_ID]='batch_id.int32\(\),'
    [REFCODE]='refcode.string\(\),'
    [PURL]='purl.string\(\),'
    [PHONE]='phone.string\(\),'
    [PKG_NAME]='pkg_name.string\(\),'
    [consumerid]='consumerid.int64\(\),'
    [age]='age.int32\(\),'
    [fico]='fico.int32\(\),'
    [open_rev_cnt]='open_rev_cnt.string\(\),'
    [utilization]='utilization.int32\(\),'
    [debt]='debt.int32\(\),'
);

#Notas
# ${!Fields[@]} = exibe o nome dos elementos no array Fields
# ${Fields[@]} = exibe o valor dos elementos no array Fields
   
numberFields=${#Fields[@]}
NF=$(awk -F, 'NR==1{print NF}' $filecsv)
declare -A headerFields
           
for ((i=1;i<=$NF;++i))
    do
        headerFields[$i]+="$(awk -v VAR=$i -F, 'NR==1{print $VAR}' $filecsv)"
        #echo ${headerFields[$i]}

        for header in ${headerFields[$i]}
        do
            arrayHeader=("${arrayHeader[@]}" "$header")
            #echo $arrayHeader
        done

    done

for field in ${!Fields[@]}
    do
        arrayField=("${!Fields[@]}" "$field")
        #echo $arrayField
    done

        for ((x=0; x<$numberFields; x++))
        do
            if [[ ${arrayHeader[x]} == ${arrayField[x]} ]]
            then
                    echo "Wright!"
                    #echo ${arrayHeader[x]}
                    #echo ${arrayField[x]}    
            else
                    echo "wrong!"
                    #echo ${arrayField[x]}
                    #echo ${arrayHeader[x]}
                    #echo "${arrayHeader[x]}-${arrayField[x]}"
            fi
        done
----------------------------------------------------------------------------------------------------------------------------------------------------------

myfile.csv:

fname,mname,lname,address,address2,CITY,ST,ZIP,SEQ_NUM,CREDIT_DAT,MAIL_DATE,MAIL_CLASS,EXP_DATE,INHOME_DATE,lasercode,BATCH_ID,REFCODE,PURL,PHONE,PKG_NAME,consumerid,age,fico,open_rev_cnt,utilization,debt
Torrence,Lynn,Earl,2219 Cowles St,,Fairbanks,AK,99701-6705,1,06/08/2021,07/22/2021,FIRST,08/27/2021,7/26/2021,SSFD,2,XY0424291,callsafestone.com/torrenceearl5,866-487-5228,D2_SS23_F,38712978,45,519,i: 7+,87,1922

Bom, a questão agora é que segundo o excelente artigo do Julio Neves, arrays associativos não são gerados em ordem numérica, logo, entendo eu que o motivo do meu if dar sempre wrong, é que ao comparar ${arrayHeader[x]} com ${arrayField[x]}, acredito qeu sempre será um teste falso, pois não estão em ordem. Fiz um echo para validar isso e ocorre o seguinte:

fname-fico
mname-open_rev_cnt
lname-lasercode
address-fname
address2-REFCODE
CITY-utilization
ST-INHOME_DATE
ZIP-PURL
SEQ_NUM-ZIP
CREDIT_DAT-MAIL_DATE
MAIL_DATE-CREDIT_DAT
MAIL_CLASS-PHONE
EXP_DATE-address
INHOME_DATE-CITY
lasercode-MAIL_CLASS
BATCH_ID-lname
REFCODE-BATCH_ID
PURL-debt
PHONE-consumerid
PKG_NAME-age
consumerid-SEQ_NUM
age-EXP_DATE
fico-address2
open_rev_cnt-ST
utilization-PKG_NAME
-mname

Eu não saberia dizer se essa ultima linha em vermelho é o único problema ou se a ordem em que ambos aparecem seria também o problema
.

Se alguém puder me ajudar a esclarecer.... sigo aqui buscando uma forma de comparar o cabeçalho de um arquivo csv com indices do meu array.

Muito obrigado desde sempre!

Em qui., 29 de jul. de 2021 às 14:01, George Robinson <george.robinson.br@gmail.com> escreveu:
Obs:

Relendo mais uma vez o material do Casanova, eu notei que nesse caso, para produzir a saída que eu preciso a estrutura do for deveria ser:

for field in "${Fields[*]}" (e não ${!Fields[@]})
    do
        echo $field
    done

Em qui., 29 de jul. de 2021 às 13:47, George Robinson <george.robinson.br@gmail.com> escreveu:
Boa tarde amigos!

Analisei o material enviado pelos sempre excelentes Alfredo e Julio Neves, e confesso que fico cada vez mais impressionado com o poder do bash para esse tipo de tarefa.

Sim, eu sempre tenho algo novo a aprender, me esforço, mas acredito que isso é algo que é necessário sempre buscar mais e mais... Eu consegui, depois de ler e reler N vezes o seguinte resultado:

#!/bin/bash
# Declara Fields
declare -A Fields
Fields=(
    [fname]='First name'.string\(\)
    [mname]='Middle name'.string\(\)
    [lname]='Last name'.string\(\)
    [address]='Address'.string\(\)
    [address2]='Address2'.string\(\)
    [CITY]='City'.string\(\)
    [ST]='state'.string\(\)
    [ZIP]='zip'.string\(\)
    [SEQ_NUM]='seq_num'.int64\(\)
    [CREDIT_DAT]='credit_dat'.string\(\)
    [MAIL_DATE]='mail_date'.string\(\)
    [MAIL_CLASS]='mail_class'.string\(\)
    [EXP_DATE]='exp_date'.string\(\)
    [INHOME_DATE]='inhome_date'.string\(\)
    [lasercode]='lasercode'.string\(\)
    [BATCH_ID]='batch_id'.int32\(\)
    [REFCODE]='refcode'.string\(\)
    [PURL]='purl'.string\(\)
    [PHONE]='phone'.string\(\)
    [PKG_NAME]='pkg_name'.string\(\)
    [consumerid]='consumerid'.int64\(\)
    [age]='age'.int32\(\)
    [fico]='fico'.int32\(\)
    [open_rev_cnt]='open_rev_cnt'.string\(\)
    [utilization]='utilization'.int32\(\)
    [debt]='debt'.int32\(\)
);
for field in "${!Fields[@]}"
    do
        Value=("${Fields[@]}" "${field[@]}")
    done
echo ${Value[@]}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Que produz a seguinte saída:

fico.int32() open_rev_cnt.string() lasercode.string() First name.string() refcode.string() utilization.int32() inhome_date.string() purl.string() zip.string() mail_date.string() credit_dat.string() phone.string() Address.string() City.string() mail_class.string() Last name.string() batch_id.int32() debt.int32() consumerid.int64() age.int32() seq_num.int64() exp_date.string() Address2.string() state.string() pkg_name.string() Middle name.string() mname

Que aredito eu que é baseado no índice mname.

Até aqui, vi que é possível gerar o valor do vetor de acordo com o índice, se eu nao estou enganado, esse resultado é um elemento único. Como eu cheguei a essa conclusão? S eu colocar o echo dentro do FOR, ele vai produzir a mesma saída para cada um dos 25 elementos do array FIELDS.

Entendo que para efeitos de comparação com o arquivo myfile.csv que possui o seguinte cabeçalho:

( fname,mname,lname,address,address2,CITY,ST,ZIP,SEQ_NUM,CREDIT_DAT,MAIL_DATE,MAIL_CLASS,EXP_DATE,INHOME_DATE,lasercode,BATCH_ID,REFCODE,PURL,PHONE,PKG_NAME,consumerid,age,fico,open_rev_cnt,utilization,debt)

eu acredito que estaria tentando comparar toda a saída do echo com cada um dos elementos do arquivo.csv.

Estaria eu enganado?

Atenciosamente,


Em qui., 29 de jul. de 2021 às 09:05, Julio C. Neves <julio.neves@gmail.com> escreveu:
Bom dia George,
não sei se entendi direito o seu problema, mas o Bash possui recursos de vetores associativos (arrays com índice alfanumérico) e tão logo esse recurso foi incorporado ao Bash, escrevi um artigo básico sobre esta técnica que está em http://www.dicas-l.com.br/cantinhodoshell/cantinhodoshell_20100120.php#.YQKYNHVKjb0

Abraços,
Julio
» Não tem tempo para fazer um curso presencial?
» Na sua cidade não tem nenhum bom curso de Linux?

Também damos treinamento em sua empresa
em qualquer cidadecom certificado e nota fiscal.








Em qua., 28 de jul. de 2021 às 20:24, George Robinson <george.robinson.br@gmail.com> escreveu:
Prezados, boa noite!

Montei um pequeno script em shell que faz a leitura de um cabeçalho CSV e os insere em um banco de dados com a seguinte estrutura:

Cabeçalho CSV:

fname,mname,lname,address,address2,CITY,ST,ZIP,SEQ_NUM
William,Dias,Maranhão,Rua Khalifa,Casa  03,Paraty,RJ,24444-444,1

neste caso, o que eu faço no meu script é pegar cada campo e assumir que a sequencia do arquivo sempre será essa. Então quando eu faço um import no banco seria algo assim:

mongoimport -h localhost:27017 -u $mobilendPrdUser -p $mobilendPasswd\
                  --db $mobilendPrdDb \
                  --collection $collection \
                  --type csv \
                  --columnsHaveTypes \
                  --fields 'First name'.string\(\),'Middle name'.string\(\),'Last name'.string\(\),'Address'.string\(\),'Address2'.string\(\),'City'.string\(\),'state'.string\(\),'zip'.string\(\),'seq_num'.int64\(\)

Porém, notei, que em alguns casos, o cabeçalho que recebo para dar carga no banco pode mudar, podendo ter mais campos à esquerda ou a direita. Sendo assim, o cabeçalho
fname,mname,lname,address,address2,CITY,ST,ZIP,SEQ_NUM pode passar a ser
email,id,fname,mname,lname,address,address2,CITY,ST,ZIP,SEQ_NUM,phone,etc ou até mesmo mudança na nomenclatura do cabeçalho (fname, passando a ser first name)

eu gostaria de ter algo como um array contendo todas as possibilidades como por exemplo (fiz em python)

dataTypes = {}
dataTypes["fname"]          = "string"
dataTypes["firstname"]      = "string"
dataTypes["first name"]     = "string"
dataTypes["mname"]          = "string"
dataTypes["middlename"]     = "string"
dataTypes["middle name"]    = "string"
dataTypes["lname"]          = "string"
dataTypes["lastname"]       = "string"
dataTypes["last name"]      = "string"
dataTypes["address"]        = "string"
dataTypes["address2"]       = "string"
dataTypes["city"]           = "string"
dataTypes["st"]             = "string"
dataTypes["state"]          = "string"
dataTypes["zip"]            = "string"
dataTypes["seq_number"]     = "int64"
dataTypes["phone"]          = "string"
dataTypes["phonenumber"]    = "string"
dataTypes["phone number"]   = "string"

A ideia seria ter um "índice" de possíveis campos de cabeçalho e "mapeá-los" de acordo com o que recebo no arquivo, já definindo o dataType dele.

Hoje meu script segue uma sequência presumida, que se quebrada, insere os campos fora de posição na tabela, o que me força a atualzar o script para bater com a sequencia recebida.

Se alguém puder me ajudar, acho que só falta essa parte pra ele ficar bem automatizado.

--
George Robinson
Analista de Suporte
Tel: +55 (21) 97449-8138
_______________________________________________
Lista brasileira de usuários de shell script
Endereço de e-mail da lista: shell-script-pt@nongnu.org
Para se inscrever ou desinscrever acesse: https://lists.nongnu.org/mailman/listinfo/shell-script-pt
Para ver os arquivos da lista (mensagens anteriores) e pesquisar nelas, acesse https://lists.nongnu.org/archive/html/shell-script-pt/

NOTA: A lista anterior, no Yahoo Groups, foi *desativada*. Por favor utilize somente esta.
_______________________________________________
Lista brasileira de usuários de shell script
Endereço de e-mail da lista: shell-script-pt@nongnu.org
Para se inscrever ou desinscrever acesse: https://lists.nongnu.org/mailman/listinfo/shell-script-pt
Para ver os arquivos da lista (mensagens anteriores) e pesquisar nelas, acesse https://lists.nongnu.org/archive/html/shell-script-pt/

NOTA: A lista anterior, no Yahoo Groups, foi *desativada*. Por favor utilize somente esta.


--
George Robinson
Analista de Suporte
Tel: +55 (21) 97449-8138


--
George Robinson
Analista de Suporte
Tel: +55 (21) 97449-8138


--
George Robinson
Analista de Suporte
Tel: +55 (21) 97449-8138
_______________________________________________
Lista brasileira de usuários de shell script
Endereço de e-mail da lista: shell-script-pt@nongnu.org
Para se inscrever ou desinscrever acesse: https://lists.nongnu.org/mailman/listinfo/shell-script-pt
Para ver os arquivos da lista (mensagens anteriores) e pesquisar nelas, acesse https://lists.nongnu.org/archive/html/shell-script-pt/

NOTA: A lista anterior, no Yahoo Groups, foi *desativada*. Por favor utilize somente esta.

_______________________________________________
Lista brasileira de usuários de shell script
Endereço de e-mail da lista: shell-script-pt@nongnu.org
Para se inscrever ou desinscrever acesse: https://lists.nongnu.org/mailman/listinfo/shell-script-pt
Para ver os arquivos da lista (mensagens anteriores) e pesquisar nelas, acesse https://lists.nongnu.org/archive/html/shell-script-pt/

NOTA: A lista anterior, no Yahoo Groups, foi *desativada*. Por favor utilize somente esta.
--



Pere

t.collons@gmail.com




------------------------------------

AVIS LEGAL

Nota de confidencialitat: Aquest missatge podria contenir missatges d'empresa i altre informació confidencial tutelada per les lleis de Europea i altres estats, Si Vostè el rep per error o sense ser una de les persones esmenades a la capçalera, haurà de destruir-lo sense copiar-lo ni revelar-l'ho o qualsevol altre acció relacionada amb el contingut del missatge i notificar-ho per correu electrònic a l'emissor del missatge.

Les persones o entitats que incompleixin els deures de confidencialitat podran ésser perseguides davant dels Tribunals de Justícia sota l'empar de la legislació civil, penal i administrativa nacional i internacional.  

Gracies per la seva cooperació.

------------------------------------

LEGAL NOTICE

Confidentiality notice: This mail may include business and other confidential information protected under the laws of and other territories. if you are not one of the intended recipients of the message, you are legally obliged to delete the message content. Furthermore, you are kindly requested to report immediately the incident to the sender.

Breach of confidentiality duties is a serious criminal offence in and other territories. Offenders shall be legally prosecuted worldwide. 

Thank you for your cooperation.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]