Perché ' non è possibile leggere da `stdin` con` read` quando si invia uno script a bash?

Non sto cercando soluzioni o soluzioni per il problema. Sto bene che non funzioni in questo modo in bash. Semplicemente non capisco perché non funziona.

Sto cercando una risposta approfondita sul perché il seguente script non funziona. Tutti i precedenti risultati di ricerca su Internet, inclusi i post di unix.stackexchange.com, non sono riusciti a chiarire completamente questo aspetto. Ha qualcosa a che fare con la lettura di read da stdin che non” funziona perché stdin è già “preso” (?) da cat nutrendo bash tramite pipe?

Script bash di esempio test.sh:

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

Metodo 1 che richiama lo script con bash test.sh:

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

Metodo 2 che esegue lo script tramite piping a bash:

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

Quindi lo script torna immediatamente al prompt, senza attendere linput o nemmeno stampare il secondo riga.

Commenti

  • Ha atteso e ricevuto input echo "Hello $NAME", quindi è terminato.

Risposta

Tu ha letto da stdin con read, ma ciò che hai letto era la riga successiva dellinput standard, ovvero echo "Hello $NAME". Dopo aver letto quella riga, non cera più input e quindi nessun altro comando da eseguire, e lo script era finito.

solo un flusso di input standard e tu “sei cercando di usarlo sia per il codice che per i dati. È lo stesso di come una sessione interattiva bash legge i comandi dalla tua digitazione, così come read risposte, così come qualsiasi altro comando che esegui desideri utilizzare linput standard.

Puoi vedere ciò che accade se aggiungiamo una riga in più alla fine dello script:

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

Entrambi forniscono un ulteriore comando per vedere lo script continuare lesecuzione e ci mostra cosa è stato letto in NAME:

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

Puoi vedere che la variabile contiene verbatim ciò che è stato scritto nel file di script – non è avvenuta alcuna interpolazione, esecuzione o espansione della variabile.


Se vuoi read dal terminale, è possibile. Il modo più semplice per funzionare è leggere dallo standard output invece che dallo standard input (!), che è presumibilmente connesso al TTY:

read NAME <&1 

Questo aspetterà che digiti qualcosa e poi passerà al resto del programma. Puoi anche utilizzare /dev/tty o $(tty).

Commenti

  • probabilmente read var </dev/tty sarebbe meglio che presumere che stdout sia connesso al contrilling tty.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *