Hvorfor er det ikke ' t muligt at læse fra `stdin` med` read , når du sender et script til at bash?

Jeg leder ikke efter løsninger eller problemer til problemet. Jeg har det fint, at det ikke fungerer sådan i bash. Jeg forstår bare ikke hvorfor det virker ikke.

Jeg leder efter et dybtgående svar, hvorfor følgende script ikke virker. Alle tidligere internetsøgeresultater, inklusive indlæg fra unix.stackexchange.com, kunne ikke rigtig rydde dette helt op. Det har noget at gøre med read læsning fra stdin hvilket ikke virker, fordi stdin allerede er” taget “(?) af cat fodring bash via røret?

Eksempel på bash-script test.sh:

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

Metode 1 kalder scriptet med bash test.sh:

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

Metode 2, der kører scriptet via piping til bash:

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

Så scriptet vender straks tilbage til prompten uden at vente på input eller endda udskrive det andet linje.

Kommentarer

  • Den ventede på og modtog input echo "Hello $NAME" og blev derefter afsluttet.

Svar

Du læste fra stdin med read, men hvad du læser var den næste linje med standardindgang – nemlig echo "Hello $NAME". Efter at have læst denne linje var der ikke mere input, og så ingen yderligere kommandoer at udføre, og scriptet var slut.

Der er kun en standardinputstrøm, og du er forsøger at bruge det til både kode og data. Dette er det samme som, hvordan en interaktiv bash -session læser kommandoer fra din indtastning samt read svar samt hvad som helst andre kommandoer, du kører, vil bruge standardinput til.

Du kan se dette ske, hvis vi tilføjer en ekstra linje i slutningen af scriptet:

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

Dette giver begge en yderligere kommando for at se scriptet fortsætte udførelsen og viser os, hvad der blev læst ind i NAME:

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

Du kan se, at variablen indeholder ordret hvad der blev skrevet i scriptfilen – der er ikke sket nogen variabel interpolering, udførelse eller udvidelse.


Hvis du vil read fra terminalen, er det muligt. enkleste måde, som sandsynligvis fungerer, er at læse fra standardoutput i stedet for standardindgang (!), som formodentlig er forbundet til TTY:

read NAME <&1 

Dette vil vente på, at jeg skriver noget, og derefter gå videre til resten af programmet. Du kan også bruge /dev/tty eller $(tty).

Kommentarer

  • uden tvivl read var </dev/tty ville være bedre end at antage, at stdout er forbundet med den sammenhængende tty.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *