Problema ao usar o comando read dentro do loop de leitura

2

Estou tentando definir uma linha loop de leitura lenta para ler um arquivo de texto de entrada linha por linha e passar duas cadeias de caracteres como variáveis em cada linha do arquivo de texto.

    while IFS= read -r line
do
    # Read and pass two path strings as variables.
    read path1 path2
    echo "$path1"
    echo "$path2"
done < "$1"

Parece processar a próxima linha no arquivo de texto em read path1 path2 antes de atribuir variáveis para cadeias em cada linha atual.

Como posso passar strings como variáveis em cada linha antes de ir para a próxima linha?

    
por obidyne 10.02.2018 / 06:49

3 respostas

3

O segundo read dentro do corpo do loop está incorreto aqui. Na verdade, vai uma linha à frente da sua primeira chamada read como parte do loop while. Então, para sua exigência, leia essas variáveis como parte do primeiro read

while read -r path1 path2; do
    echo "$path1"
    echo "$path2"
done < "$1"

Como você vê aqui, a configuração IFS= também está incorreta, ao ler duas variáveis, porque a redefinição do separador de campo apenas pega a linha como um todo. Por ter seu valor padrão (caracteres de espaço em branco, tabulação e nova linha), a leitura de duas variáveis armazenará os valores de cada linha em uma lista separada por espaços. Dessa forma, poderíamos ter uma linha delimitada por n colunas e usar n variáveis para ler.

Agora os valores estão disponíveis nessas variáveis que você poderia passar para outros comandos conforme necessário.

Vamos ver como isso funciona para um arquivo de entrada de amostra

foo bar
foo1 bar1
foo2 bar2

Executando o primeiro script no modo de depuração com -x set

$ bash -x script.sh
+ read -r path1 path2
+ echo 1
1
+ echo 2
2
+ read -r path1 path2
+ echo 3
3
+ echo 4
4
+ read -r path1 path2
+ echo abc
abc
+ echo def
def
+ read -r path1 path2
    
por 10.02.2018 / 06:54
0

Com o redirecionamento do arquivo para o loop for , todas as leituras da entrada padrão no loop inteiro serão lidas no mesmo arquivo. Isso significa que os dois comandos read no loop lerão linhas alternativas de qualquer arquivo que você passar como o primeiro argumento para o seu script.

É um pouco incerto para mim onde você deseja que os dados de path1 e path2 sejam fornecidos. Se estas forem lidas do arquivo, simplesmente faça isso na cabeça do loop:

while read -r path1 path2; do
    printf 'path1 = "%s"\n' "$path1"
    printf 'path2 = "%s"\n' "$path2"
done <"somefile"

O restante desta resposta assume que você quer ler algo do arquivo e, em seguida, no loop, do terminal.

Para tornar o read no corpo do loop lido a partir do terminal:

exec 3<"somefile"

while IFS= read -r words <&3; do
   read -r word1 word2 junk
   printf 'Got words = "%s"\n' "$words"
   printf 'Got word1 = "%s"\n' "$word1"
   printf 'Got word2 = "%s"\n' "$word2"
done

Isso faz com que a entrada para o primeiro read venha do arquivo somefile , enquanto o fluxo de entrada padrão do segundo read será lido do terminal (ou de onde vem o fluxo de entrada padrão do script).

    
por 10.02.2018 / 10:16
0

Se você quiser que a linha intacta e extraia valores dela, você pode usar um here-string :

while IFS= read -r line; do
    read -r path1 path1 <<< "$line"
    echo "$line"
    echo "$path1:$path2"
done < file

Na verdade, nem todos os shells suportam strings aqui. No entanto, todos os shells do tipo POSIX suportam documentos aqui.

while IFS= read -r line; do
    read -r path1 path1 << _LINE_
$line
_LINE_
    echo "$line"
    echo "$path1:$path2"
done < file
    
por 10.02.2018 / 22:00