Bash: lire l'entrée dans la boucle de lecture ne fonctionne pas

14

La lecture de l'entrée dans une boucle de lecture en temps ne semble pas fonctionner

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

l'exécution ne s'arrête pas comme si la lecture avait été effectuée en dehors de la boucle. Pourquoi est-ce? Existe-t-il une solution de contournement pour lire les entrées dans une boucle de lecture while?

bien en fait
la source

Réponses:

15

Le problème est qu'à la fois read lineet read responseattend (et obtient) des données de stdin.
Cette question sur SO explique certains d'entre eux avec un lien vers encore plus d'informations.

tl; dr
La réponse acceptée suggère:

Lire depuis le terminal de contrôle: read input </dev/tty

Nifle
la source
16

laissez la commande de lecture interne utiliser stdin et utilisez un descripteur de fichier différent pour la boucle while

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

Nifle a tout à fait raison. Cependant, lorsque vous utilisez plusieurs terminaux, vous devez être précis.

Pour ceux d'entre vous qui viennent de Google, félicitations pour avoir trouvé cette page. Si vous devez faire une entrée utilisateur pendant un certain temps boucle de lecture (ce qui comprend rm -i, readou quoi que ce soit d' autre), vous pouvez spécifier tuyau d'alimentation à utiliser.

Voici un fragment de cette solution que j'ai utilisée:

#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
la source
1

Merci Nifle! Et aussi grâce à bgStack. Après avoir cherché pendant des heures, j'ai finalement obtenu la réponse! Elle est bonne!! J'ai utilisé "echo $ (tty)" pour détecter mon chemin de terminal ou vous le prenez simplement comme variable. Pour moi, c'était un autre cas d'utilisation. U lisait un fichier et voudrait confirmer l'exécution. Peut-être que l'exemple ci-dessous aide quelqu'un d'autre.

#!/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
la source
Dans mon cas , j'avais whilelu à partir d' une pipe ... puis je redirection de lire stdin: read something < %terminal.
eftshift0