Analisando um arquivo de texto delimitado no bash como argumentos do comando

10

Eu tenho um arquivo de texto dividido da seguinte forma:

field1,field2,field3 
xield1,xield2,xield3 
dield1,dield2,dield3 
gield1,gield2,gield3

Cada uma dessas colunas será um parâmetro para um programa, e eu gostaria que o programa fosse chamado para cada linha

Eu estava esperando por um loop, algo como:

for $i in file
    command $field2 -x $field3 -PN -$field1 >> output
done

Qual seria a melhor maneira de realizar algo assim em bash?

    
por Dean 05.12.2013 / 23:26

5 respostas

6

while IFS=, read xx yy zz;do
    echo $xx $yy $zz
done < input_file

Isso deve funcionar se o número de campos for constante. Em vez de echo use seu comando.

    
por 05.12.2013 / 23:40
3

Você deve usar um while com o read integrado:

while IFS= read -r line;do
    fields=($(printf "%s" "$line"|cut -d',' --output-delimiter=' ' -f1-))
    command "${fields[1]}" -x "${fields[2]}" ... # ${fields[1]} is field 2
done < your_file_here

Como isso funciona

  • A instrução cut pega a linha e a divide no delimitador especificado por -d .
  • O --output-delimiter é o caractere separador que cut usará para exibir os campos selecionados, aqui escolhemos um espaço para podermos colocar os diferentes campos na matriz fields .
  • Finalmente, queremos todos os campos (do campo 1 ao final) e é aí que entra -f1- .
  • Agora você tem os diferentes campos armazenados na variável da matriz fields , você pode acessar qualquer campo específico desejado com a sintaxe ${field[number]} , em que number é um a menos que o número real do campo desejado, pois a indexação da matriz é baseado em zero no Bash.

Nota

  • Isso falhará se algum dos seus campos contiver espaço em branco.

Para um número constante de campos

Você pode fazer algo semelhante a resposta do 1_CR :

while IFS= read -r line;do
    IFS=, read -r field1 field2 field3 <<-EOI
    $line
    EOI
    command "$field2" -x "$field3" ... 
done < your_file_here

O acima, embora pareça mais barulhento, deve funcionar em qualquer shell compatível com POSIX, não apenas Bash.

    
por 05.12.2013 / 23:28
1

Você pode obter read para dividir cada linha em uma matriz em , definindo IFS apropriadamente.

while IFS=, read -r -a input; do
 printf "%s\n" "${input[0]}" "${input[1]}"
done < input.txt

Assim, no exemplo acima, você pode acessar cada elemento da matriz usando seu índice, começando com 0.

    
por 05.12.2013 / 23:38
1

Esse awk one-liner fará o que você quiser:

awk -F, '{cmd="echo " $2 " -x " $3 " -PN " $1 ">> output";  system(cmd)}' f.txt

Substitua echo pelo seu comando e f.txt pelo arquivo pelo qual você deseja iterar.

Breve explicação: -F, irá definir , como delimitador. cmd constrói o comando e system(cmd) chama o comando.

    
por 05.12.2013 / 23:43
1

gnu sed pode ser usado também.

sed infile -e 's!^\([^,]*\),\([^,]*\),\([^,]*\)$!command  -x  -PN !e' >> output

observe o uso da opção e no comando s

    
por 06.12.2013 / 00:05