Estoy tratando de hacer que bash procese datos de stdin que se canalizan, pero no tuve suerte. Lo que quiero decir es que ninguno de los siguientes trabajos:
echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=
echo "hello world" | read test; echo test=$test
test=
echo "hello world" | test=`cat`; echo test=$test
test=
donde quiero que esté la salida test=hello world
. He intentado poner "" comillas "$test"
que tampoco funcionan.
shopt -s lastpipe
- tldp.org/LDP/abs/html/bashver4.html#LASTPIPEOPTRespuestas:
Utilizar
Usted puede engañar
read
a aceptar de una tubería de la siguiente manera:o incluso escribir una función como esta:
Pero no tiene sentido: ¡sus asignaciones variables pueden no durar! Una canalización puede generar una subshell, donde el entorno se hereda por valor, no por referencia. Es por eso
read
que no se molesta con la entrada de una tubería: no está definida.Para su información, http://www.etalabs.net/sh_tricks.html es una colección ingeniosa de la migaja necesaria para combatir las rarezas e incompatibilidades de las conchas de bourne, sh.
fuente
test=`echo "hello world" | { read test; echo $test; }`
{}
lugar de()
agrupar esos dos comandos?read
una entrada de entrada desde la tubería, sino en usar la variable en el mismo shell que ejecuta elread
.bash permission denied
al intentar usar esta solución. Mi caso es muy diferente, pero no pude encontrar una respuesta para cualquier lugar, lo que funcionó para mí era (un ejemplo diferente, pero uso similar):pip install -U echo $(ls -t *.py | head -1)
. En caso de que alguien tenga un problema similar y se encuentre con esta respuesta como yo.si desea leer muchos datos y trabajar en cada línea por separado, puede usar algo como esto:
si desea dividir las líneas en varias palabras, puede usar múltiples variables en lugar de x de esta manera:
alternativamente:
Pero tan pronto como comience a querer hacer algo realmente inteligente con este tipo de cosas, será mejor que use un lenguaje de script como perl donde pueda probar algo como esto:
Hay una curva de aprendizaje bastante empinada con perl (o supongo que cualquiera de estos idiomas), pero a la larga le resultará mucho más fácil si desea hacer algo más que los guiones más simples. Recomiendo el Perl Cookbook y, por supuesto, el lenguaje de programación Perl de Larry Wall et al.
fuente
read
no leerá de una tubería (o posiblemente el resultado se pierda porque la tubería crea una subshell). Sin embargo, puede usar una cadena here en Bash:Pero vea la respuesta de @ chepner para obtener información sobre
lastpipe
.fuente
Esta es otra opción
fuente
<(..)
tiene$(..)
es que<(..)
devuelve cada línea a la persona que llama tan pronto como el comando que ejecuta la pone a disposición.$(..)
, sin embargo, espera a que el comando se complete y genere toda su salida antes de poner cualquier salida a disposición de la persona que llama.No soy un experto en Bash, pero me pregunto por qué esto no se ha propuesto:
Prueba única de que funciona para mí:
fuente
bash
4.2 introduce lalastpipe
opción, que permite que su código funcione como está escrito, ejecutando el último comando en una tubería en el shell actual, en lugar de un subshell.fuente
La sintaxis para una tubería implícita de un comando de shell en una variable bash es
o
En sus ejemplos, está canalizando datos a una declaración de asignación, que no espera ninguna entrada.
fuente
El primer intento estuvo bastante cerca. Esta variación debería funcionar:
y la salida es:
Necesita llaves después de la tubería para encerrar la tarea a probar y el eco.
Sin las llaves, la asignación para probar (después de la tubería) está en un shell, y el eco "test = $ test" está en un shell separado que no conoce esa asignación. Es por eso que estaba obteniendo "test =" en la salida en lugar de "test = hello world".
fuente
En mi opinión, la mejor manera de leer stdin en bash es la siguiente, que también te permite trabajar en las líneas antes de que termine la entrada:
fuente
Como me enamoro, me gustaría dejar una nota. Encontré este hilo, porque tengo que reescribir un antiguo script sh para que sea compatible con POSIX. Esto básicamente significa evitar el problema de tubería / subshell introducido por POSIX reescribiendo código como este:
dentro:
Y código como este:
dentro:
Pero este último no se comporta igual en la entrada vacía. Con la antigua notación, el bucle while no se ingresa en una entrada vacía, ¡pero en la notación POSIX sí! Creo que se debe a la nueva línea antes de EOF, que no se puede omitir. El código POSIX que se comporta más como la antigua notación se ve así:
En la mayoría de los casos, esto debería ser lo suficientemente bueno. Pero desafortunadamente, esto todavía no se comporta exactamente como la antigua notación si some_command imprime una línea vacía. En la antigua notación, el cuerpo while se ejecuta y en la notación POSIX nos separamos frente al cuerpo.
Un enfoque para solucionar esto podría verse así:
fuente
Un script inteligente que puede leer datos de PIPE y argumentos de línea de comando:
Salida:
Explicación: Cuando una secuencia de comandos recibe datos a través de una tubería, entonces el stdin / proc / self / fd / 0 será un enlace simbólico a una tubería.
Si no, apuntará a la terminal actual:
La
[[ -p
opción bash puede verificar si es una tubería o no.cat -
lee el destdin
.Si usamos
cat -
cuando no haystdin
, esperará para siempre, por eso lo ponemos dentro de laif
condición.fuente
/dev/stdin
cuál es un enlace a/proc/self/fd/0
Colocar algo en una expresión que involucra una tarea no se comporta así.
En cambio, intente:
fuente
El siguiente código:
funcionará también, pero abrirá otro nuevo sub-shell después de la tubería, donde
no lo haré
Tuve que deshabilitar el control de trabajo para hacer uso del método de chepnars (estaba ejecutando este comando desde la terminal):
Bash Manual dice :
Nota: el control de trabajo está desactivado de forma predeterminada en un shell no interactivo y, por lo tanto, no necesita el
set +m
guión interno.fuente
Creo que estabas tratando de escribir un script de shell que podría recibir información de stdin. pero mientras intentas hacerlo en línea, te perdiste tratando de crear esa prueba = variable. Creo que no tiene mucho sentido hacerlo en línea, y es por eso que no funciona de la manera esperada.
Estaba tratando de reducir
para obtener una línea específica de varias entradas. para poder escribir ...
así que necesito un pequeño programa de shell capaz de leer desde stdin. como tu lo haces.
Ahí tienes.
fuente
Qué tal esto:
fuente