¿Por qué no puedo canalizar la entrada en el comando `read` en Bash, en Cygwin, usando ConEmu, en Windows?


0

Estoy tratando de almacenar la salida de una tubería en una variable.

Después de leer este post ( Accediendo a la salida de una tubería Bash con 'leer' ), Tenía algunas dudas para recordar si alguna vez tuve éxito en hacer eso, en un sistema Unix.

Entonces encontré este post ( ¿Cómo hacer un bucle a través de los nombres de archivos devueltos por encontrar? ), y se le recordó que funciona, a veces utilizando read -r <varname> también.

Ambiente:

User@Computer /cygdrive/...
$ echo $SHELL
/bin/bash

User@Computer /cygdrive/...
$ echo $BASH_VERSION
4.4.5(1)-release

User@Computer /cygdrive/...
$ uname -a
CYGWIN_NT-10.0 Computer 2.6.1(0.305/5/3) 2016-12-16 11:55 x86_64 

User@Computer /cygdrive/...
$ read --help
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
    Read a line from the standard input and split it into fields.

Intentos de

User@Computer /cygdrive/...
$ echo $var


User@Computer /cygdrive/...
$ echo "hi" | read var

User@Computer /cygdrive/...
$ echo $var


User@Computer /cygdrive/...
$ echo "hi" | read -r var

User@Computer /cygdrive/...
$ echo $var

User@Computer /cygdrive/...
$ read var
hi

User@Computer /cygdrive/...
$ echo $var
hi

User@Computer /cygdrive/...
$ echo "hi" | cat
hi

User@Computer /cygdrive/...
$ echo -e '1\n2\n3\n' | xargs
1 2 3

También probé esto en bash.exe Proceso propio y ventana:

User@Computer /cygdrive/...
$ echo "hi" | read var;echo $var;

También haciendo lo mismo en el "Bash en Ubuntu en Windows" bash.exe:

echo "hi" | read var;echo $var;

Todavía no hay resultado exitoso de la tarea. Soy consciente de que puedo evitar este método, en lugar de eso, probablemente use $() o las flechas de redireccionamiento.

¿Hay una manera de hacer esto usando este read ¿Método de comando de línea en Windows?

Actualizar

Para algunas de las respuestas, sabía que algunas postearían alternativas como $(). Esta es la razón por la que ya mencioné este método intencionalmente, incluido un enlace donde ya se enumeraron varios, y pregunté específicamente si había alguna forma de usar el read Utilidad de línea para almacenar la entrada en una variable, no utilizando redireccionamiento, sino canalizando datos a través de una cadena de comandos, como lo había hecho antes en otros sistemas, pero esta vez en Windows.


1
esto sucede porque la lectura se ejecuta en una subshell, y cualquier variable creada en esa subshell se destruye al salir. ver: mywiki.wooledge.org/BashFAQ/024 . la solución más sencilla es utilizar una tubería con nombre
Sharuzzaman Ahmat Raslan

1
Tu segundo enlace funciona solo en el formulario. something | while read var; do use $var; done porque todo el bucle while forma el extremo derecho de la tubería y se ejecuta en una subshell; el ajuste de var es ido después del final del bucle while. @SharuzzamanAhmatRaslan: aunque bash 4.2+ (como en esta Q) tiene shopt lastpipe para cambiar esto en un script.
dave_thompson_085

Interesante: stackoverflow.com/questions/36340599/… Probablemente no lo use de esta manera, ya que todavía veo varias versiones diferentes de bash Alrededor, y quiero ser más compatible con ellos.
Pysis

Respuestas:


0

Puedes usar la tubería con nombre.

Ejemplo:

sharuzzaman@laptop /cygdrive/...
$ mkfifo mypipe

sharuzzaman@laptop /cygdrive/...
$ echo "hi" > mypipe &
[1] 5260

sharuzzaman@laptop /cygdrive/...
$ read asdf < mypipe

sharuzzaman@laptop /cygdrive/...
$ echo $asdf
hi
[1]+  Done                    echo "hi" > mypipe

0

Para resultados de una sola línea, la forma canónica de hacer esto en bash es:

variable=$(the_command the_command_args)

por ejemplo:

today=$(date +%Y%m%d) 

(y los argumentos de comando pueden contener $ -variables si es necesario).

Para los resultados de varias minas, utiliza un ciclo para procesar cada línea sucesivamente:

for f in $(ls -1)
do
    echo @@@@"$f"
done

0

Para las otras respuestas, parecen enfoques ordenados con algunos buenos ejemplos, pero tenía mucha curiosidad por la razón de que este enfoque de que había estado usando ad-hoc y en algunos scripts de shell, el funcionamiento "dejado de funcionar" o no funcionara en mi Windows sistema.

No vi que publicaron ninguna respuesta directamente relacionada con cómo puedo lograr esto con el uso read y tuberías, así que aquí está mi actualización como una forma de cierre donde pruebo algunos ejemplos y resalto la funcionalidad específica a la que se ha aludido.

Bueno, a los comentarios sobre la pregunta, puedo mostrar que esto funciona en mi sistema Mac (10.12.5), en iTerm 3.0.15, en el fish cáscara:

⋊> ~ echo "hi" | read var;echo $var;
hi
⋊> ~ fish -v
fish, version 2.6.0

Cuando hacen referencia a una subshell que se está utilizando, parece que funciona en fish, que entiendo de alguna manera tiene una arquitectura y un patrón de diseño diferentes, aunque en algunas partes esperaría capas que funcionen de manera similar, al menos desde la perspectiva de un caso de uso.

Luego intenté el enfoque de nuevo en mi Mac, en ambos intérpretes.

En fish:

⋊> ~ echo -ne '1\n2\n3\n' | while read line; echo "a$line""a"; end
a1a
a2a
a3a

En bash:

bash-3.2$ echo -ne '1\n2\n3\n' | while read line; do echo "a$line""a"; done
a1a
a2a
a3a

bash-3.2$ echo $BASH
/bin/bash
bash-3.2$ echo $BASH_VERSION
3.2.57(1)-release

Toda la funcionalidad parece estar (en su mayoría) funcionando como se espera aquí. Me sorprendió un poco encontrar que la variable no daba salida bash, pero mi problema original pensé era que los datos esperados no persistían en ese bucle. Tendré que revisar mi código más de cerca teniendo en cuenta todo esto.

Resultado final

El punto principal que se resalta aquí es no almacenar la entrada estándar en variables simples ingresando bash y continuar normalmente en un script, ya que se ejecuta en una subshell, de acuerdo con Sharuzzaman Ahmat Raslan y dave_thompson_085 .

En su lugar, funciona de esa manera en fish, o simplemente puedo ser más cuidadoso al trabajar directamente en la cadena de tuberías con el bucle while, y volver a revisar mi código para estos problemas.

Otras notas

Creo que otro problema en una de mis líneas de código era que estaba tratando de usar read -r <varname>, pero terminé entrando read -p <varname> en lugar. Este último consume un argumento adicional para formar una solicitud para el comando de lectura, y en mi ejemplo con solo 1 argumento, no deja un nombre de variable útil para almacenar información y recuperarla. El primero a veces es útil en los ejemplos de otros cuando no se quiere usar secuencias de escape de retroceso, siempre que sea eso. Así que evita los errores tipográficos como este!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.