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
- Read the second line.
- Assign the value "I \ t fine" to
And so on.
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=) prevents leading or
IFS=space characters (space or tab) from being removed.
-rprevents the backslash (
\) from being interpreted as a special character.
|| [[ -n $linea ]]prevents the last line from being ignored if it does not end with
readreturns a non-zero exit when it encounters an EOF). Theoretically, a line must end with
\nand is defined by POSIX : Sequence of zero or more characters other than a new line
\nfollowed 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:
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!
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.<
|| [[ -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
$ 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
- How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
- What does IFS= do in this bash loop:
cat file | while IFS= read -r line; do … done
- Read a file line by line assigning the value to a variable