Hvorfor er det ikke ' det er mulig å lese fra `stdin` med` read når du sender et skript til å bash?

Jeg er ikke på utkikk etter løsninger rundt problemet. Jeg har det bra med at det ikke fungerer slik i bash. Jeg forstår bare ikke hvorfor det fungerer ikke.

Jeg ser etter et grundig svar på hvorfor følgende skript ikke fungerer. Alle tidligere søkeresultater på internett, inkludert innlegg fra unix.stackexchange.com, kunne ikke ordne dette helt opp. Det har noe å gjøre med read å lese fra stdin som ikke fungerer fordi stdin allerede er» tatt «(?) av cat fôring bash via røret?

Eksempel på bash-skript test.sh:

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

Metode 1 som kaller skriptet med bash test.sh:

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

Metode 2 kjører skriptet via piping til bash:

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

Så skriptet går umiddelbart tilbake til ledeteksten uten å vente på input eller til og med å skrive ut det andre linje.

Kommentarer

  • Den ventet på og mottok input echo "Hello $NAME", og ble deretter avsluttet.

Svar

Du leste fra stdin med read, men det du leste var neste linje med standardinngang – nemlig echo "Hello $NAME". Etter å ha lest den linjen, var det ikke mer input og så ingen ytterligere kommandoer å utføre, og skriptet var over.

Det er bare en standard inngangsstrøm, og du er prøver å bruke den til både kode og data. Dette er det samme som hvordan en interaktiv bash -økt leser kommandoer fra typen du skriver, så vel som read svar, så vel som andre kommandoer du kjører vil bruke standard inngang til.

Du kan se dette skje hvis vi legger til en ekstra linje til slutten av skriptet:

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

Dette gir begge en ytterligere kommando for å se skriptet fortsette kjøringen, og viser oss hva som ble lest inn i NAME:

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

Du kan se at variabelen inneholder ordrett det som ble skrevet i skriptfilen – ingen variabel interpolering, utførelse eller utvidelse har skjedd.


Hvis du vil read fra terminalen, er det mulig. enkleste måten som sannsynligvis fungerer, er å lese fra standardutgang i stedet for standardinngang (!), som antagelig er koblet til TTY:

read NAME <&1 

Dette vil vente på at jeg skriver inn noe, og deretter gå videre til resten av programmet. Du kan også bruke /dev/tty eller $(tty).

Kommentarer

  • uten tvil read var </dev/tty ville være bedre enn å anta at stdout er koblet til den samlende tytien.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *