1. Overview
We work with text all the time. Thus, we need a way to access the text in files. One way is to read the lines of text into arrays. Hence, we often need a way to access the file contents in a structured manner.
In this tutorial, we’ll learn different ways to read the lines of a file into an array.
The steps have been verified on Ubuntu version 20.04.
2. Sample Data
Before we look at the various approaches, let’s view the example.txt file populated with some lines of text. This will be our sample data:
$ cat example.txt
This is an example file.
This is a test file.
This is a file for this tutorial.
The cat output shows the content of the example.txt file. It contains three lines with the mandatory newline at the end.
3. The Internal Field Separator Value
Several approaches that we’ll discuss use the internal field separator (IFS) value. Let’s see what the default value of IFS is first:
IFS=$' \t\n'
Now, we check that it currently holds the default value:
$ echo -n "$IFS" | cat -ET
^I$
The echo command is used to write messages to the standard output. The message is enclosed between two double quotations. The output is piped to the cat command. Then, cat again redirects to the standard output. The standard output forwards to the screen by default.
Importantly, we’re using the -ET option to display special characters. The -E option adds a dollar sign to the end of each line. On the other hand, the -T option displays tabs as ^I.
So, IFS currently has its default value. Let’s change that to only the newline:
$ IFS=$'\n'
Let’s verify that it has been changed:
$ echo -n "$IFS" | cat -ET
$
Since the IFS value includes a newline, we see a dollar sign.
4. Using the while read Loop Approach
The first approach that we will see is the while loop approach.
First, we define an array named arr which is empty:
$ arr=()
$ while read line; do
arr+=("$line")
done < example.txt
Then, we define a while loop where < example.txt redirects the file content to its standard input. Thus, the while loop iterates over all the lines. In each iteration, the loop control statement reads a single line from the standard input using the read command.
Each separate line becomes a value of the line variable. Correspondingly, we append the value of the line variable to the arr array. The while loop terminates when no more lines can be read from the standard input.
On each iteration, we only read a single line, because the internal field separator (IFS) value is a newline. Therefore, all the words of the read line are assigned to the variable line.
5. Using the read Command
An alternative is using the read command on its own.
As we’ve seen in the while loop approach, only a single line is read in each read call. Hence, we need to set an option that allows us to read the whole file. The -d option tells the read command to continue until EOF:
$ read -a array_example -d EOF < example.txt
The read command takes the input string (from the standard input) and places it in the array variable specified by the option -a. The line boundary is the value of IFS.
6. The for Loop Approach
Same as while, we can use a for loop for our needs. As we did previously with the while loop approach, we define an array named arr which is empty:
$ arr=()
$ for line in $(cat example.txt); do
arr+=("$line")
done
Next, we define a for loop that iterates over the string value of the cat command result. The IFS value is a newline, therefore the for loop iterates over the string line by line. Correspondingly, it appends the value of the line to the array arr. The for loop terminates when it processes the whole string of the $(cat example.txt) result.
7. Using the mapfile or readarray Commands
Another way of reading a file into an array is using the mapfile command. The mapfile command reads input from the standard input and stores it in an array:
$ mapfile -t array_example < example.txt
The mapfile command stores each line as a separate value in the array. The -t option removes any trailing newlines.
After running the mapfile command, there’s no screen output and no error messages. Therefore, we assume that we managed to read the file lines and transfer them.
As stated in its manual, the readarray command is a synonym for the mapfile command. Hence, the functionality is the same for both.
8. Using the cat Command
A different approach to read input from a file into an array is using the cat command.
We want to define an array such that the values of the array are the individual lines of the result of the cat example.txt command.
Before we define the array, we set the value of the IFS to the newline:
$ IFS=$'\n'
Then, we declare an array with its values set to the content of the string returned by the cat command:
$ array_example=($(cat example.txt))
Here, the syntax is the main driver. Since the IFS value is a newline, the content of the string is split by the newline character.
9. Verifying the Array
Finally, we want to make sure the resulting array holds the right content after reading the lines from the file.
For this, we use a for loop to access and echo the individual values in the array:
$ for value in "${array_example[@]}"; do
echo "$value"
done
Considering our sample data, we expect the file lines to appear on the screen:
This is an example file.
This is a test file.
This is a file for this tutorial.
The values of the array are the output strings of the individual lines.
10. Conclusion
In this article, we looked at several approaches to reading lines from a file into an array.
Some required the use of IFS, while others provided a way to use separate delimiters. Depending on the scenario, we can choose different options.