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
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.
echo "Hello $NAME"
og blev derefter afsluttet.