linux – How can I read the content of a file line by line with Bash?

Question:

I have a file with this content:

Hola qué tal
Yo \t muy bien
    Un placer.

I want to read it line by line, saving the value of each line in a variable for processing.

That is, I want:

  • Read the first line.
  • Assign the value "Hello how are you" to the variable $ line.
  • Do things with $linea .
  • Read the second line.
  • Assign the value "I \ t fine" to $linea .

And so on.

Answer:

Use while ... do ... done < fichero with some nuance:

while IFS='' read -r linea || [[ -n "$linea" ]]; do
    printf ">%s<\n" "$linea"
done < fichero

What is explained as:

  • IFS='' (or IFS= ) prevents leading or IFS= space characters (space or tab) from being removed.
  • -r prevents the backslash ( \ ) from being interpreted as a special character.
  • || [[ -n $linea ]] prevents the last line from being ignored if it does not end with \n (since read returns a non-zero exit when it encounters an EOF). Theoretically, a line must end with \n and is defined by POSIX : Sequence of zero or more characters other than a new line \n followed by a new line character . However, it may be the case that a file has been written in which the last line does not contain it; with this addition, that line would also be processed.

Thus, in your file we would have this output:

$ while IFS= read -r linea || [[ -n "$linea" ]]; do printf ">%s<\n" "$linea"; done < fichero
>Hola qué tal<
>Yo \t muy bien<
>   Un placer.<

Let's see what would happen if we removed any of the checks:

Without IFS='' : leading and trailing spaces are removed.

$ while read -r linea || [[ -n "$linea" ]]; do printf ">%s<\n" "$linea"; done < a
>Hola qué tal<
>Yo \t muy bien<
>Un placer.<      # ¡esto tenía espacios al principio!

Without -r in read : the backslash is interpreted.

$ while IFS= read linea || [[ -n "$linea" ]]; do printf ">%s<\n" "$linea"; done < a
>Hola qué tal<
>Yo t muy bien<   # ¡aquí había un \t!
>   Un placer.<

Without || [[ -n $linea ]] : a hypothetical last line not ending in \n not be read:

Given the previous file, if we add a new series of characters without a final \n :

$ printf "ueee" >> fichero

We observe that its content appears in this way:

$ cat -vet fichero
Hola quM-CM-) tal$
Yo \t muy bien$
   Un placer.$
ueee              # se superpone al prompt

When we read, this last line is not processed:

$ while IFS= read -r linea; do printf ">%s<\n" "$linea"; done < fichero
>Hola qué tal<
>Yo \t muy bien<
>   Un placer.<   # la línae ueee" no se lee

Referencias:

Scroll to Top