Como otimizar o script com NF e um loop for

Tenho vários arquivos, cada um com um número diferente de colunas. Quero convertê-los para inseri-los em um banco de dados

Por exemplo, o arquivo test01:

0001 000000000000001 john smith 45 500 0002 000000000000002 peter jackson 20 80 0003 000000000000002 robert brown 35 100 0004 000000000000007 sarah white 40 300 

Minha saída desejada é:

("0001","000000000000001","john smith","45","500"), ("0002","000000000000002","peter jackson","20","80"), ("0003","000000000000002","robert brown","35","100"), ("0004","000000000000007","sarah white","40","300"); 

para conseguir isso, uso o seguinte script:

cat test01 |awk -F"\t" "{print "("\"""$1""\"","\"""$2""\"","\"""$3""\"","\"""$4""\"","\"""$5""\""),"}" |sed "$ s/.$/;/" 

E funciona bem, o problema é quando encontro outro arquivo com um número diferente de colunas, então tenho que modificar o script manualmente.

Eu sei que posso obter o número de colunas com a variável NF do AWK, mas como combinar esta variável com um loop for no script?

Quando tento

cat test01 | awk "{for (i = 1; i <= NF; i++){print $i""\"","\"""}}" 

Obtenho este resultado:

0001"," 000000000000001"," john"," smith"," 45"," 500"," 0002"," 000000000000002"," peter"," jackson"," 20"," 80"," 0003"," 000000000000002"," robert"," brown"," 35"," 100"," 0004"," 000000000000007"," sarah"," white"," 40"," 300"," 

Comentários

  • No arquivo original, há um delimitador de tabulação ou apenas " algum espaço em branco "?
  • É um delimitador de tabulação

Resposta

Usando GNU sed:

$ sed -e "s/^/("/" -e "s/\t/","/g" -e "s/$/"),/" -e "$s/.$/;/" file ("0001","000000000000001","john smith","45","500"), ("0002","000000000000002","peter jackson","20","80"), ("0003","000000000000002","robert brown","35","100"), ("0004","000000000000007","sarah white","40","300"); 

O o script tem quatro partes:

  1. s/^/("/ substitui o início da linha por (".
  2. s/\t/","/g substitui as guias por ",". Este é o bit que requer GNU sed. Para outras sed implementações, insira uma guia literal no lugar de \t.
  3. s/$/"),/ substitui o final da linha por "),.
  4. $s/.$/;/ substitui a vírgula no final do última linha (apenas) com ;.

Comentários

  • Eu executo o script e avisa " > " como esperando por algo
  • @ user3333911 Eu tinha citações incompatíveis de uma versão anterior. Corrigido agora e testado.

Resposta

Se seu arquivo de entrada for separado por tabulações, você pode tentar o seguinte:

awk -F"\t" -vq=""" -vOFS="","" "$1=$1 {print "(" q $0 q ");"}" filename 

Ou incorpore aspas na função de impressão:

awk -F"\t" -vOFS="","" "$1=$1 {print "(" "\x27" $0 "\x27" ");"}" filename 

Comentários

  • Observe as vírgulas no final de todas as linhas, exceto a última …
  • Bom aviso @Kusalananda. Fiz uma correção rápida como em awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'. Alguma sugestão melhor?
  • Não, essa ' é uma boa solução.

Resposta

Para alcançar o mesmo comportamento que você deseja com seu script inicial, você pode usar o método “printf” do awk. Torna possível se livrar de novas linhas que são colocadas por “imprimir”. Eu estou supondo que seu script deve ser reescrito assim:

cat test01 | awk "{for (i = 1; i <= NF; i++){printf $i""\"","\"""}; printf "\n";}" 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *