Preámbulo
Uno de los errores más comunes cuando se aprende a utilizar los scripts “
bash” bajo
GNU/Linux para leer un archivo línea por línea, es el utilizar un bucle “
for”, (
for line in $(cat file.txt); do ...) lo que conduce a una evaluación de cada palabra y no de cada línea, que es lo que se busca.
Ejemplo de un bucle “for”:
for line in $(cat file.txt); do echo "$line" ; done
Esta
Es
La
Línea
n°
1
Esta
Es
La
Línea
n°
2
Esta
[...]
La solución consiste en utilizar un bucle “
while” asociado al comando interno “
read”.
Sin embargo, también podemos obtener el mismo resultado con un bucle “
for” con la condición de que cambiemos el valor de la variable "
$IFS" (
Internal Field Separator, separador de campo interno) antes de ejecutar el bucle. Es lo que veremos a continuación.
Bucle while
El bucle “while” sigue siendo el método más apropiado y simple para leer un archivo línea por línea.
Sintaxis
while read linea
do
comando
done < archivo
Ejemplo
El archivo de inicio:
Esta es la línea n° 1
Esta es la línea n° 2
Esta es la línea n° 3
Esta es la línea n° 4
Esta es la línea n° 5
Las instrucciones en línea de comandos:
while read line; do echo -e "$line\n"; done < file.txt
o en un script “bash”:
#! /bin/bash
while read line
do
echo -e "$line\n"
done < file.txt
La salida en la pantalla será (stdout):
Esta es la línea n° 1
Esta es la línea n° 2
Esta es la línea n° 3
Esta es la línea n° 4
Esta es la línea n° 5
Trucos
También podemos a partir de un archivo estructurado (
como una libretas de direcciones o /etc/passwd por ejemplo) obtener los valores de cada campo y asignarlos a varias variables con el comando “
read”. Sin embargo hay que tener cuidado de asignar a la variable “
IFS” el separador de campo adecuado (
espacio por defecto).
Ejemplo:
#! /bin/bash
while IFS=: read user pass uid gid full home shell
do
echo -e "$full :\n\
Pseudo : $user\n\
UID :\t $uid\n\
GID :\t $gid\n\
Home :\t $home\n\
Shell :\t $shell\n\n"
done < /etc/passwd
Complemento
while read i; do echo -e "parametro : $i"; done < <(echo -e "a\nab\nc")
Bucle for
Si bien es cierto que el bucle “while” es el método más simple, sin embargo este tiene un gran inconveniente, el de eliminar el formateado de las líneas y especialmente los espacios y tabulaciones.
Felizmente el bucle “for” asociado a un cambio de IFS permite conservar la estructura del documento a la salida.
Sintaxis
oldIFS=$IFS # conserva el separador de campo
IFS=$'\n' # nuevo separador de campo, el caracter fin de línea
for línea in $(cat archivo)
do
comando
done
IFS=$old_IFS # restablece el separador de campo predeterminado