Proč není ' t možné při pipování skriptu do bash číst z `stdin` s` read ?

Nevyhledávám řešení problému ani řešení. Jsem v pohodě, protože to nefunguje v bash. Jen nerozumím proč to nefunguje.

Hledám podrobnou odpověď, proč následující skript nefunguje. Všechny předchozí výsledky internetového vyhledávání, včetně příspěvků z unix.stackexchange.com, to úplně nevyřeší. Má to něco společného s read čtením z stdin který nefunguje, protože stdin je již“ převzat „(?) cat krmením bash pomocí kanálu?

Příklad bash skriptu test.sh:

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

Metoda 1 volání skriptu s bash test.sh:

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

Metoda 2 spuštění skriptu pomocí pipingu na bash:

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

Takže skript se okamžitě vrátí na výzvu, aniž by čekal na zadání nebo dokonce vytiskl druhou řádek.

Komentáře

  • Čekal a přijal vstup echo "Hello $NAME", poté byl ukončen.

Odpověď

Vy četl ze stdin pomocí read, ale to, co jste četli, byl další řádek standardního vstupu – konkrétně echo "Hello $NAME". Po přečtení tohoto řádku již nebyl žádný vstup, a tedy žádné další příkazy k provedení, a skript skončil.

Existuje pouze jeden standardní vstupní proud a vy jste znovu snaží se jej použít pro kód i data. Je to stejné, jako když interaktivní relace bash čte příkazy z vašeho psaní a také read odpovědi, stejně jako jakékoli další spuštěné příkazy, pro které chcete použít standardní vstup.

Tuto událost můžete vidět, pokud na konec skriptu přidáme další řádek:

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

Toto poskytuje další příkaz, který umožňuje pokračovat v provádění skriptu, a ukazuje nám, co bylo načteno do NAME:

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

Vidíte, že proměnná obsahuje doslovně to, co bylo napsáno v souboru skriptu – nedošlo k žádné interpolaci, spuštění ani rozšíření proměnné.


Pokud chcete read z terminálu, je to možné. nejjednodušší způsob, jak pravděpodobně fungovat, je číst ze standardního výstupu namísto standardního vstupu (!), který je pravděpodobně připojen k TTY:

read NAME <&1 

This počká, až něco napíšu, a poté přejde na zbytek programu. Můžete také použít /dev/tty nebo $(tty).

Komentáře

  • pravděpodobně read var </dev/tty by bylo lepší, než předpokládat, že standardní výstup je spojen s vzrušující desítkou.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *