En esta entrada aprendemos y refrescamos el conocimiento de leer archivos línea a línea, cuando elaboramos un script o guion en Bash. Cabe decir que es una nota para mis apuntes, ya que, con tantas cosas en la cabeza, me las tengo que apuntar en el algún lado, y que mejor que este humilde blog. Así que, sin más preámbulo, vamos al turrón.



Leer un archivo línea a línea en Bash

Veamos primero la sintaxis habitual. Esta consiste en leer cada línea de la siguiente manera:

1 2 3 4 while IFS = read -r line do echo " $line " done < input_file while IFS= read -r line do echo "$line" done < input_file

O bien, podemos hacer lo mismo en una sola línea:

1 while IFS = read -r line; do echo $line ; done < input_file while IFS= read -r line; do echo $line; done < input_file

¿Qué hemos hecho?

El archivo de entrada (“input_file”) es el nombre del archivo que deseamos que esté abierto para su lectura mediante el comando “read”. Dicho comando lee el archivo línea por línea, asignando cada línea a la variable de línea. Una vez que se procesan todas las líneas, el bucle “while” terminará. El separador de campo interno (IFS) se establece en la cadena nula para conservar los espacios en blanco iniciales y finales, que es el comportamiento predeterminado del comando de lectura (read)

Ejemplos para leer un archivo línea a línea

Veamos el siguiente ejemplo. Supongamos que tenemos un archivo llamado distros.txt que contiene una lista de algunas de las distribuciones de GNU/Linux más populares y sus gestores de paquetes separados con coma (,) :

1 2 3 4 5 6 distros.txt Ubuntu,apt Debian,apt CentOS, yum Arch Linux,pacman Fedora,dnf distros.txt Ubuntu,apt Debian,apt CentOS,yum Arch Linux,pacman Fedora,dnf

Para leer el archivo línea por línea, ejecutaremos el siguiente código en su terminal:

1 2 3 4 while IFS = read -r line do echo " $line " done < distros.txt while IFS= read -r line do echo "$line" done < distros.txt

El código leerá el archivo por línea, asignará la línea a una variable y hará eco de la variable. Básicamente veríamos la misma salida como si mostrara el contenido del archivo con el comando cat.

¿Qué sucede si deseamos imprimir solo las distribuciones que usan apt? Una forma sería verificar si la línea contiene la subcadena “apt”, como sigue:

1 2 3 4 5 6 while IFS = read -r line do if [ [ " $line " == * "apt" * ] ] ; then echo " $line " fi done < distros.txt while IFS= read -r line do if [[ "$line" == *"apt"* ]]; then echo "$line" fi done < distros.txt

Con la salida:

1 2 Ubuntu,apt Debian,apt Ubuntu,apt Debian,apt

Al leer el archivo línea por línea, también podemos pasar más de una variable al comando de lectura, que dividirá la línea en campos basados en el IFS. El primer campo se asigna a la primera variable, el segundo a la segunda variable, y así sucesivamente. Si hay más campos que variables, los campos restantes se asignan a la última variable.

En el siguiente ejemplo, estamos configurando IFS a una coma (,) y pasando dos variables “distro” y “pm” al comando de lectura. Todo desde el principio de la línea hasta la primera coma se asignará a la primera variable (distro) y el resto de la línea se asignará a la segunda variable (pm):

1 2 3 4 while IFS =, read -r distro pm do echo " $pm " is the package manager for " $distro " done < distros.txt while IFS=, read -r distro pm do echo "$pm" is the package manager for "$distro" done < distros.txt

Con la salida:

1 2 3 4 5 apt is the package manager for Ubuntu apt is the package manager for Debian yum is the package manager for CentOS pacman is the package manager for Arch Linux dnf is the package manager for Fedora apt is the package manager for Ubuntu apt is the package manager for Debian yum is the package manager for CentOS pacman is the package manager for Arch Linux dnf is the package manager for Fedora

Métodos alternativos de lectura de archivos

Usando una sustitución de proceso

La sustitución de procesos nos permite pasar la salida del comando como un nombre de archivo:

1 2 3 4 while IFS = read -r line do echo " $line " done < < ( cat input_file ) while IFS= read -r line do echo "$line" done < <(cat input_file )

Usando un string

Aquí el valor “string” es una variante del documento. La cadena (cat input_file) mantendrá las nuevas líneas:

1 2 3 4 while IFS = read -r line do echo " $line " done <<< $ ( cat input_file ) while IFS= read -r line do echo "$line" done <<< $(cat input_file )

Usando el descriptor de archivo

También podemos proporcionar la entrada al bucle utilizando un descriptor de archivo:

1 2 3 4 while IFS = read -r -u9 line do echo " $line " done 9 < input_file while IFS= read -r -u9 line do echo "$line" done 9< input_file

Cuando trabajemos con descriptores de archivos, debemos utilizar un número entre 4 y 9 para evitar conflictos con los descriptores de archivos internos del shell.

Conclusión

En Bash, podemos leer un archivo línea por línea al proporcionar el nombre del archivo como una entrada para un ciclo de tiempo de lectura.

Respecto a las fuentes consultadas

El artículo es una adaptación de la siguiente entrada:

Linuxsize.com – How to Read a File Line by Line in Bash