Bash: ler a entrada dentro enquanto o loop de leitura não funcionar


14

Ler a entrada dentro de um loop de leitura while não parece funcionar

while read line
do
 echo "get some input from the user"
 read response
done < some_file.txt

a execução não pausa como se a leitura estivesse fora do loop. Por que é isso? Existe uma solução alternativa para a leitura de entrada em um loop de leitura while?

Respostas:


15

O problema é que ambos read linee read responseesperam (e obtêm) dados stdin.
Esta pergunta sobre o SO explica parte dela com um link para ainda mais informações.

tl; dr
A resposta aceita sugere:

Leia a partir do dispositivo terminal de controle: read input </dev/tty


16

deixe o comando de leitura interna usar stdin e use um descritor de arquivo diferente para o loop while

while read -u 3 line; do
  read -p "get some input from the user" response
done 3< some_file.txt

1

Nifle está exatamente correto. Quando você usa vários terminais, no entanto, precisa ser específico.

Para aqueles que vêm do google, parabéns por encontrar esta página. Se você precisa fazer qualquer entrada do usuário durante um loop de leitura while (isso inclui rm -i, readou qualquer outra coisa), você pode especificar qual o tubo de entrada para o uso.

Aqui está um fragmento desta solução que eu usei:

#in declarations
thistty=$(tty)

lsuser -R LDAP -a home pgrp ALL 2>/dev/null | while read line
do
   homedir=$(echo $homedir | awk -F= '{print $2}')
   sudo rm -ir "$homedir" < $thistty
done

1

Obrigado Nifle! E também graças ao bgStack. Depois de procurar por horas, finalmente consegui a resposta! Muito bom!! Eu usei "echo $ (tty)" para detectar meu caminho de terminal ou você apenas o considera variável. Para mim, foi outro caso de uso. U estava lendo um arquivo e gostaria de confirmar a execução. Talvez o exemplo abaixo ajude mais alguém.

#!/bin/bash

export terminal=$(tty)

cat file | while read val1 val2
do
   while true; 
            do
              read -p "would you like to XYZ" yn
              case $yn in
                        [Yy]* )     echo "# Move $val1 to $val2        #";break;;
                        [Nn]* )     echo "#---------no action----------#";break;;
                        * )         echo "# Please answer yes or no.   #";;
              esac
            done < $terminal
done

No meu caso eu tinha whilede ler a partir de um tubo ... e então eu usei o redirecionamento para ler de stdin: read something < %terminal.
eftshift0
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.