Pourquoi nest-il pas ' possible de lire depuis `stdin` avec` read` lors du transfert dun script vers bash?

Je « ne cherche pas de solution de contournement ou de solution au problème. Je » suis daccord avec le fait que cela ne fonctionne pas comme ça dans bash. Je ne comprends simplement pas pourquoi ça ne marche pas.

Je cherche une réponse détaillée pourquoi le script suivant ne fonctionne pas. Tous les résultats de recherche Internet précédents, y compris les publications de unix.stackexchange.com, n’ont pas pu clarifier complètement ce point. Cela a quelque chose à voir avec la lecture read de stdin qui ne fonctionne pas car stdin est déjà » pris « (?) par cat alimentant bash via le tube?

Exemple de script bash test.sh:

echo "Please say name:" read NAME echo "Hello $NAME" 

Méthode 1 appelant le script avec bash test.sh:

$ bash test.sh Please say name: XYZ Hello XYZ $ 

Méthode 2 exécutant le script via piping vers bash:

$ cat test.sh | bash Please say name: $ 

Le script revient donc immédiatement à linvite, sans attendre lentrée ni même imprimer la seconde ligne.

Commentaires

  • Il a attendu et reçu lentrée echo "Hello $NAME", puis sest terminé.

Réponse

Vous lu depuis stdin avec read, mais ce que vous avez lu était la ligne suivante de lentrée standard – à savoir echo "Hello $NAME". Après avoir lu cette ligne, il ny avait plus dentrée et donc plus de commandes à exécuter, et le script était terminé.

Il ny a quun flux dentrée standard, et vous « re essayez de lutiliser à la fois pour le code et les données. Cela revient à la façon dont une session bash interactive lit les commandes de votre saisie, ainsi que read, ainsi que toutes les autres commandes que vous exécutez pour lesquelles vous souhaitez utiliser lentrée standard.

Vous pouvez voir que cela se produit si nous ajoutons une ligne supplémentaire à la fin du script:

echo "Please say name:" read NAME echo "Hello $NAME" printf "name=%s\n" "$NAME" 

Ceci fournit à la fois une commande supplémentaire pour voir le script continuer lexécution et nous montre ce qui a été lu dans NAME:

Please say name: name=echo "Hello $NAME" 

Vous pouvez voir que la variable contient verbatim ce qui a été écrit dans le fichier de script – aucune interpolation, exécution ou expansion de variable ne sest produite.


Si vous souhaitez read depuis le terminal, cest possible. Le moyen le plus simple qui est susceptible de fonctionner est de lire à partir de la sortie standard au lieu de lentrée standard (!), qui est probablement connectée au TTY:

read NAME <&1 

Ceci attendra que je tape quelque chose, puis passera au reste du programme. Vous pouvez également utiliser /dev/tty ou $(tty).

Commentaires

  • sans doute read var </dev/tty serait mieux que de supposer que stdout est connecté au terminal de contrôle.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *