¿Cómo leer la entrada multilínea de la entrada estándar en una variable y cómo imprimir una en Shell (sh, bash)?

StackOverflow https://stackoverflow.com/questions/212965

  •  03-07-2019
  •  | 
  •  

Pregunta

Lo que quiero hacer es lo siguiente:

  1. leer en entrada de varias líneas desde stdin en variable A
  2. realizar diversas operaciones en A
  3. tubo A sin perder los símbolos delimitadores (\n,\r,\t,etc) a otro comando

El problema actual es que no puedo leerlo con read comando, porque deja de leer en una nueva línea.

Puedo leer stdin con cat, como esto:

my_var=`cat /dev/stdin`

, pero luego no sé cómo imprimirlo.De modo que la nueva línea, la tabulación y otros delimitadores sigan ahí.

Mi script de muestra se ve así:

#!/usr/local/bin/bash

A=`cat /dev/stdin`

if [ ${#A} -eq 0 ]; then
        exit 0
else
        cat ${A} | /usr/local/sbin/nextcommand
fi
¿Fue útil?

Solución

Esto está funcionando para mí:

myvar=`cat`

echo "$myvar"

Las citas alrededor de $myvar son importantes.

Otros consejos

En Bash, hay una forma alternativa; man bash menciona:

  

La sustitución del comando $(cat file) se puede reemplazar por el equivalente pero más rápido $(< file).

$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test

tee hace el trabajo

#!/bin/bash
myVar=$(tee)

Sí, a mí también me funciona. Gracias.

myvar=`cat`

es lo mismo que

myvar=`cat /dev/stdin`

Bueno, sí. Desde la página de manual de bash:

  

Encerrar caracteres entre comillas dobles   conserva el valor literal de todos   personajes dentro de las comillas,   con la excepción de $, `, \ y cuando la expansión del historial es   habilitado,!. Los caracteres $ y `   retener su significado especial entre comillas dobles.

Si le interesa preservar las nuevas líneas al final de la salida, use esto:

myVar=$(cat; echo x)
myVar=${myVar%x}
printf %s "$myVar"

Esto utiliza el truco de aquí .

.

[actualizado]

Esta tarea se bloqueará indefinidamente si no hay nada en la tubería...

var="$(< /dev/stdin)"

Sin embargo, podemos evitar esto haciendo un tiempo de espera. read para el primer personaje.Si se agota el tiempo de espera, el código de retorno será mayor que 128 y conoceremos la tubería STDIN (también conocida como /dev/stdin) esta vacio.

De lo contrario, obtenemos el resto de STDIN por...

  • configuración IFS a NULL solo para el read dominio
  • apagando escapes con -r
  • eliminando el delimitador de lectura con -d ''.
  • y finalmente, agregar eso al personaje que obtuvimos inicialmente.

De este modo...

__=""
_stdin=""

read -N1 -t1 __  && {
  (( $? <= 128 ))  && {
    IFS= read -rd '' _stdin
    _stdin="$__$_stdin"
  }
}

Esta técnica evita el uso var="$(command ...)" Sustitución de comando que, por diseño, siempre eliminará las nuevas líneas finales.

Si se prefiere la sustitución de comandos, para preservar las nuevas líneas finales podemos agregar uno o más caracteres delimitadores a la salida dentro del $() y luego quítelos afuera.

Por ejemplo ( nota $(parens) en el primer comando y ${braces} en segundo )...

_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top