Miksi ' t ei ole mahdollista lukea sanasta ”stdin” ja ”read”, kun ohjaat komentosarjaa bashiin?

En etsi kiertotapoja tai ratkaisuja ongelmaan. Hyvin, jos se ei toimi näin bash. En vain ymmärrä miksi se ei toimi.

Etsin syvällistä vastausta, miksi seuraava komentosarja ei toimi. Kaikkia aiempia Internet-hakutuloksia, mukaan lukien unix.stackexchange.com-sivuston viestit, ei voitu tyhjentää tätä kokonaan. Sillä on jotain tekemistä read -kohdan kanssa, joka on luettu kohteesta stdin joka ei toimi, koska stdin on jo” otettu ”(?) cat syötteen bash putken kautta?

Esimerkki bash-komentosarjasta test.sh:

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

Tapa 1 kutsutaan komentosarjaa bash test.sh:

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

Tapa 2, joka ajaa komentosarjan bash:

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

Joten komentosarja palaa välittömästi kehotteeseen odottamatta syötettä tai edes tulostamalla toista rivi.

Kommentit

  • Se odotti ja vastaanotti syötettä echo "Hello $NAME" ja lopetti sitten.

Vastaa

Sinä luki stdinistä read, mutta lukemasi oli seuraava vakiosyötön rivi – nimittäin echo "Hello $NAME". Kun olet lukenut kyseisen rivin, syötettä ei enää ollut eikä enää komentoja suoritettavaksi, ja komentosarja oli ohi.

Vain yksi vakiosyöttövirta on olemassa, ja olet yritetään käyttää sitä sekä koodiin että tietoihin. Tämä on sama kuin miten vuorovaikutteinen bash -istunto lukee kirjoittamasi komennot sekä read vastaukset sekä kaikki muut suorittamasi komennot haluavat käyttää vakiosyöttöä.

Näet tämän tapahtuvan, jos lisäämme ylimääräisen rivin komentosarjan loppuun:

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

Tämä antaa molemmille uuden komennon nähdäksesi komentosarjan suorituksen jatkumisen, ja näyttää meille mitä luettiin NAME:

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

Voit nähdä, että muuttuja pitää sisällään verbatim sen, mikä on kirjoitettu komentosarjatiedostoon – muuttujan interpolointia, suorittamista tai laajentamista ei ole tapahtunut.


Jos haluat read päätelaitteelta, se on mahdollista. yksinkertaisin tapa, joka todennäköisesti toimii, on lukea vakiolähdöstä vakiotulon (!) sijaan, joka on oletettavasti liitetty TTY: hen:

read NAME <&1 

Tämä odottaa minun kirjoittavan jotain ja siirtyy sitten muuhun ohjelmaan. Voit käyttää myös /dev/tty tai $(tty).

Kommentit

  • epäilemättä read var </dev/tty olisi parempi kuin olettaa, että stdout on kytketty supistuvaan tty: hen.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *