Iterando sobre cadenas de líneas múltiples almacenadas en variable

17

Yo leí que es malo para las cosas de escritura como for line in $(command), la forma correcta parece ser en su lugar:

command | while IFS= read -r line; do echo $line; done

Esto funciona muy bien. Pero, ¿qué sucede si lo que quiero repetir es el contenido de una variable , no el resultado directo de un comando?

Por ejemplo, imagine que crea el siguiente archivo quickfox:

The quick brown
foxjumps\ over -
the
lazy ,
dog.

Me gustaría poder hacer algo como esto:

# This is just for the example,
# I could of course stream the contents to `read`
variable=$(cat quickfox);
while IFS= read -r line < $variable; do echo $line; done; # this is incorrect
Sheljohn
fuente

Respuestas:

19

En shells modernos como bash y zsh, tiene un redirector `<<< 'muy útil que acepta una cadena como entrada. Entonces harías

while IFS= read -r line ; do echo $line; done <<< "$variable"

De lo contrario, siempre puedes hacer

echo "$variable" | while IFS= read -r line ; do echo $line; done
lgeorget
fuente
Lo siento, debería haber pensado en hacer eco de los contenidos, por supuesto. Pero gracias por la respuesta rápida de todos modos!
Sheljohn el
1
necesita comillas dobles $variablecuando lo usa, de lo contrario, el whilebucle obtendrá solo una línea de entrada. Véase, por ejemplo, la diferencia de salida entre echo $variablevs echo "$variable"o cat <<< $variablevs cat <<< "$variable".
cas
@cas En realidad, depende de lo que hay dentro de $ variable. En el caso presentado por el OP ("variable = $ (cat quickfox)") funciona sin las comillas adicionales. Pero para el caso general, tienes razón. Edito mi respuesta. Gracias.
lgeorget
La variable=$(cat quickfox)pregunta en el OP en sí proporciona un ejemplo de lo que estaba hablando. El uso $variablede comillas dobles internas incluye las nuevas líneas, el uso sin las nuevas líneas se traduce en espacios por el shell. Si está leyendo y procesando línea por línea, esto hace una gran diferencia: con el primero tiene múltiples líneas de entrada, con el último solo tiene una línea de entrada. Los datos de entrada son superficialmente similares pero, en la práctica, completamente diferentes en esos dos casos.
cas
por ejemplo: con esos datos de entrada, cat <<< "$variable" | wc -ldevuelve 5. cat <<< $variable | wc -ldevuelve 1. Si desea / necesita preservar espacios en blanco (incluyendo líneas nuevas, tabulaciones, espacios simples o múltiples) en una variable, DEBE comillas dobles la variable cuando la use, de lo contrario todos se transformarán en un solo espacio entre cada "palabra".
cas