Miért nem lehet ' olvasni a `stdin-ből a` read-val, amikor egy scriptet bash-ba vezetünk?

Nem keresek megoldási lehetőségeket vagy megoldásokat a problémára. Jól vagyok, ha nem úgy működik, mint a bash. Csak azt nem értem, hogy miért nem működik.

Mélyreható választ keresek arra, hogy miért nem működik a következő szkript. Az összes korábbi internetes keresési eredmény, beleértve az unix.stackexchange.com bejegyzéseit, “nem igazán tisztázható ki teljesen. Van valami köze a read stdin amely nem működik, mert a stdin -t már” elvette “(?) cat bash a csövön keresztül?

Példa bash szkriptre test.sh:

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

1. módszer a szkript meghívása a következővel: bash test.sh:

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

2. módszer a parancsfájl futtatása a bash:

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

Tehát a parancsfájl azonnal visszatér a parancssorba, anélkül, hogy megvárná a bevitelt, vagy akár ki is nyomtatná a másodikat sor.

Megjegyzések

  • Várta és megkapta a bemenetet echo "Hello $NAME", majd leállt.

Válasz

Ön olvasott a stdin-ből read -vel, de amit olvasott, az a következő szabványos bemenet sora volt: echo "Hello $NAME". Miután elolvasta ezt a sort, nem volt több bevitel, ezért nem volt további végrehajtandó parancs, és a parancsfájlnak vége lett.

Csak egy normál bemeneti adatfolyam van, és Ön megpróbálja használni mind a kódhoz, mind az adatokhoz. Ez megegyezik azzal, ahogy az interaktív bash munkamenet olvassa a gépelésből származó parancsokat, valamint a read válaszok, valamint bármely más futtatott parancs normál bevitelt akar használni.

Láthatja, hogy ez történik, ha egy extra sort adunk a szkript végéhez:

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

Ez egy további parancsot nyújt a parancsfájl végrehajtásának folytatásához, és megmutatja, mi olvasható be NAME:

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

Láthatja, hogy a változó szó szerint tartalmazza a szkriptfájlba írtakat – nem történt változó interpoláció, végrehajtás vagy bővítés.


Ha a terminálról read szeretne, akkor lehetséges. A legegyszerűbb módja annak, hogy valószínűleg a szabványos kimenetről olvasunk be a standard bemenet helyett (!), amely feltehetően a TTY-hez kapcsolódik:

read NAME <&1 

Ez megvárja, hogy begépeljek valamit, majd folytatom a program többi részével. Használhatja a következőt is: /dev/tty vagy $(tty).

Megjegyzések

  • vitathatatlanul read var </dev/tty jobb lenne, mintha azt feltételeznénk, hogy az stdout kapcsolódik az összehúzódó tty-hez.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük