¿Cómo se itera correctamente sobre las líneas en bash, ya sea en una variable o desde la salida de un comando? Simplemente establecer la variable IFS en una nueva línea funciona para la salida de un comando, pero no cuando se procesa una variable que contiene nuevas líneas.
Por ejemplo
#!/bin/bash
list="One\ntwo\nthree\nfour"
#Print the list with echo
echo -e "echo: \n$list"
#Set the field separator to new line
IFS=$'\n'
#Try to iterate over each line
echo "For loop:"
for item in $list
do
echo "Item: $item"
done
#Output the variable to a file
echo -e $list > list.txt
#Try to iterate over each line from the cat command
echo "For loop over command output:"
for item in `cat list.txt`
do
echo "Item: $item"
done
Esto da la salida:
echo:
One
two
three
four
For loop:
Item: One\ntwo\nthree\nfour
For loop over command output:
Item: One
Item: two
Item: three
Item: four
Como puede ver, hacer eco de la variable o iterar sobre el cat
comando imprime cada una de las líneas correctamente una por una. Sin embargo, el primer bucle for imprime todos los elementos en una sola línea. ¿Algunas ideas?
Respuestas:
Con bash, si desea incrustar nuevas líneas en una cadena, encierre la cadena con
$''
:Y si ya tiene una cadena de este tipo en una variable, puede leerla línea por línea con:
fuente
done <<< "$list"
es crucialdone <<< "$list"
es crucial porque eso pasará "$ list" como la entrada aread
$list
son muy cruciales.echo "$list" | while ...
podría parecer más claro que... done <<< "$line"
Puedes usar
while
+read
:Por cierto. La
-e
opciónecho
no es estándar. Use en suprintf
lugar, si desea portabilidad.fuente
<<<
versión sugerida por Glenn Jackman no funciona con la asignación de variables.while
pieza. La<<<
versión no lo hace (en nuevas versiones de bash, al menos).fuente
IFS=$'\n'
para el mismo efecto.Aquí hay una forma divertida de hacer tu bucle for:
Un poco más sensible / legible sería:
Pero eso es demasiado complejo, solo necesitas un espacio allí:
Usted
$line
variable no contiene saltos de línea. Contiene instancias de\
seguido porn
. Puedes ver eso claramente con:La sustitución está reemplazando aquellos con espacios, lo cual es suficiente para que funcione en bucles:
Manifestación:
fuente
cr
puedes usar$'\n'
.También puede convertir primero la variable en una matriz, luego iterar sobre esto.
Esto solo es útil si no desea meterse con el comando
IFS
y también tiene problemas con elread
comando, ya que puede suceder, si llama a otro script dentro del bucle, ese script puede vaciar su búfer de lectura antes de regresar, como me sucedió a mí .fuente