I thought setting IFS to $'\n'
would help me in reading an entire file into an array, as in:
IFS=$'\n' read -r -a array < file
However, the above command only reads the first line of the file into the first element of the array, and nothing else.
Even this reads only the first line into the array:
string=$'one\ntwo\nthree'
IFS=$'\n' read -r -a array <<< "$string"
I came across other posts on this site that talk about either using mapfile -t
or a read
loop to read a file into an array.
Now my question is: when do I use IFS=$'\n'
at all?
You are a bit confused as to what IFS is. IFS is the Internal Field Separator used by bash to perform word-splitting to split lines into words after expansion. The default value is [ \t\n]
(space, tab, newline).
By reassigning IFS=$'\n'
, you are removing the ' \t'
and telling bash to only split words on newline
characters (your thinking is correct). That has the effect of allowing some line with spaces
to be read into a single array element without quoting.
Where your implementation fails is in your read -r -a array < file
. The -a
causes words in the line to be assigned to sequential array indexes. However, you have told bash to only break on a newline
(which is the whole line). Since you only call read once, only one array index is filled.
You can either do:
while IFS=$'\n' read -r line; do
array+=( $line )
done < "$filename"
(which you could do without changing IFS
if you simply quoted "$line"
)
Or using IFS=$'\n'
, you could do
IFS=$'\n'
array=( $(<filename) )
or finally, you could use IFS
and readarray
:
readarray array <filename
Try them and let me know if you have questions.