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?

bem, na verdade
fonte

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

Nifle
fonte
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
Glenn Jackman
fonte
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
bgStack15
fonte
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
Micha
fonte
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