¿Por qué no ' t es posible leer desde `stdin` con` read` al canalizar un script a bash?

No estoy buscando soluciones alternativas para el problema. Estoy bien con que no funcione así en bash. Simplemente no entiendo por qué no funciona.

Estoy buscando una respuesta detallada por qué el siguiente script no funciona. Todos los resultados de búsqueda de Internet anteriores, incluidas las publicaciones de unix.stackexchange.com, no pudieron aclarar esto por completo. Tiene algo que ver con read leer de stdin que no» funciona porque stdin ya está «tomado» (?) por cat alimentando bash a través de la tubería?

Ejemplo de secuencia de comandos bash test.sh:

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

Método 1 llamando al script con bash test.sh:

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

Método 2 ejecutando el script mediante una canalización a bash:

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

Por tanto, el script vuelve inmediatamente al indicador, sin esperar a que se ingrese o incluso imprimir el segundo línea.

Comentarios

  • Esperó y recibió la entrada echo "Hello $NAME", luego terminó.

Responder

leyó desde stdin con read, pero lo que leyó fue la siguiente línea de entrada estándar, a saber, echo "Hello $NAME". Después de leer esa línea, no hubo más entrada y, por lo tanto, no hubo más comandos para ejecutar, y el script terminó.

Hay solo un flujo de entrada estándar, y usted » tratando de usarlo tanto para código como para datos. Esto es lo mismo que la forma en que una sesión interactiva bash lee los comandos de tu escritura, así como read respuestas, así como cualquier otro comando que ejecute para el que desee usar la entrada estándar.

Puede ver que esto sucede si agregamos una línea adicional al final del script:

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

Esto proporciona un comando adicional para ver que el script continúa la ejecución y nos muestra lo que se leyó en NAME:

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

Puede ver que la variable contiene palabra por palabra lo que se escribió en el archivo de secuencia de comandos; no se ha producido ninguna interpolación, ejecución o expansión de variables.


Si desea read desde la terminal, es posible. La forma más sencilla que probablemente funcione es leer desde la salida estándar en lugar de la entrada estándar (!), que presumiblemente está conectada al TTY:

read NAME <&1 

Este esperará a que escriba algo y luego pasará al resto del programa. También puede utilizar /dev/tty o $(tty).

Comentarios

  • podría decirse que read var </dev/tty sería mejor que asumir que stdout está conectado al tty contrilling.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *