Como ler linhas diferentes de um arquivo para diferentes variáveis?

13

Eu gostaria de ler diferentes linhas de um arquivo de texto para diferentes variáveis. Por exemplo

input.txt :

line1 foo foobar bar
line2 bar
line3 foo
line4 foobar bar

Eu quero que esse resultado seja armazenado nas variáveis var1 , var2 , var3 e var4 de tal forma

var1=line1 foo foobar bar
var2=line2 bar

e assim por diante.

Alguém poderia me dizer como isso é feito? Eu tentei usar eval em um loop for. Não parece funcionar.

    
por neet 25.01.2017 / 10:17

3 respostas

20

Você faria:

unset -v line1 line2
{ IFS= read -r line1 && IFS= read -r line2; } < input.txt

Ou:

{ line1=$(line) && line2=$(line); } < input.txt

(menos eficiente, pois line raramente é embutido e a maioria das shells precisam ser forçadas para implementar a substituição de comandos. line também não é mais um comando padrão).

Para usar um loop:

unset -v line1 line2 line3
for var in line1 line2 line3; do
  IFS= read -r "$var" || break
done < input.txt

Ou para definir automaticamente os nomes das variáveis como line<++n> :

n=1; while IFS= read -r "line$n"; do
  n=$((n + 1))
done < input.txt

Observe que bash suporta variáveis de matriz e readarray incorporado para ler linhas em uma matriz:

readarray -t line < input.txt

Observe, entretanto, que ao contrário da maioria dos outros shells, bash array indices começam em 0 não 1 (herdado de ksh ), então a primeira linha estará em ${line[0]} , não ${line[1]} (embora como @Costas mostrou , você pode fazer com que readarray (aka mapfile ) comece a escrever os valores no indice 1 ( bash arrays também ao contrário da maioria dos outros shells sendo Matrizes esparsas ) com -O 1 ).

Veja também: Entenda "IFS = read -r line"?

    
por 25.01.2017 / 10:26
11

Eu me ofereceria para usar o array para essa (s) tarefa (s)

mapfile -t -O 1 var <input.txt

, então você terá cada linha em ${var[1]} , ${var[2]} e assim por diante

    
por 25.01.2017 / 10:32
0

Isso não é estritamente o que você pediu, mas pode funcionar para as suas necessidades. Você pode serializar os dados com Awk. Note que isso vai quebrar se o seu $ 1 não é um nome da variável válida:

awk '
function quote(str,   d, m, x, y, z) {
  d = ""; m = split(str, x, d)
  for (y in x) z = z d x[y] (y < m ? d "\" d : d)
  return z
}
{
  print $1 "=" quote($0)
}
' input.txt > /tmp/input.sh
. /tmp/input.sh

Resultado:

$ echo "$line1"
line1 foo foobar bar
    
por 26.01.2017 / 00:49

Tags