Read lines from a file into a Bash array

ArraysBash

Arrays Problem Overview


I am trying to read a file containing lines into a Bash array.

I have tried the following so far:

#Attempt1

a=( $( cat /path/to/filename ) )

#Attempt2

index=0
while read line ; do
	MYARRAY[$index]="$line"
	index=$(($index+1))
done < /path/to/filename

Both attempts only return a one element array containing the first line of the file. What am I doing wrong?

I am running bash 4.1.5

Arrays Solutions


Solution 1 - Arrays

The readarray command (also spelled mapfile) was introduced in bash 4.0.

readarray -t a < /path/to/filename

Solution 2 - Arrays

Latest revision based on comment from BinaryZebra's comment and tested here. The addition of command eval allows for the expression to be kept in the present execution environment while the expressions before are only held for the duration of the eval.

Use $IFS that has no spaces\tabs, just newlines/CR

$ IFS=$'\r\n' GLOBIGNORE='*' command eval  'XYZ=($(cat /etc/passwd))'
$ echo "${XYZ[5]}"
sync:x:5:0:sync:/sbin:/bin/sync

Also note that you may be setting the array just fine but reading it wrong - be sure to use both double-quotes "" and braces {} as in the example above


Edit:

Please note the many warnings about my answer in comments about possible glob expansion, specifically gniourf-gniourf's comments about my prior attempts to work around

With all those warnings in mind I'm still leaving this answer here (yes, bash 4 has been out for many years but I recall that some macs only 2/3 years old have pre-4 as default shell)

Other notes:

Can also follow drizzt's suggestion below and replace a forked subshell+cat with

$(</etc/passwd)

The other option I sometimes use is just set IFS into XIFS, then restore after. See also Sorpigal's answer which does not need to bother with this

Solution 3 - Arrays

The simplest way to read each line of a file into a bash array is this:

IFS=$'\n' read -d '' -r -a lines < /etc/passwd

Now just index in to the array lines to retrieve each line, e.g.

printf "line 1: %s\n" "${lines[0]}"
printf "line 5: %s\n" "${lines[4]}"

# all lines
echo "${lines[@]}"

Solution 4 - Arrays

One alternate way if file contains strings without spaces with 1string each line:

fileItemString=$(cat  filename |tr "\n" " ")

fileItemArray=($fileItemString)

Check:

Print whole Array:

${fileItemArray[*]}

Length=${#fileItemArray[@]}

Solution 5 - Arrays

Your first attempt was close. Here is the simplistic approach using your idea.

file="somefileondisk"
lines=`cat $file`
for line in $lines; do
        echo "$line"
done

Solution 6 - Arrays

#!/bin/bash
IFS=$'\n' read  -d '' -r -a inlines  < testinput
IFS=$'\n' read  -d '' -r -a  outlines < testoutput
counter=0
cat testinput | while read line; 
do
    echo "$((${inlines[$counter]}-${outlines[$counter]}))"
    counter=$(($counter+1))
done
# OR Do like this
counter=0
readarray a < testinput
readarray b < testoutput
cat testinput | while read myline; 
do
    echo value is: $((${a[$counter]}-${b[$counter]}))
    counter=$(($counter+1))
done

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHomunculus ReticulliView Question on Stackoverflow
Solution 1 - ArrayschepnerView Answer on Stackoverflow
Solution 2 - ArraysnhedView Answer on Stackoverflow
Solution 3 - ArrayssorpigalView Answer on Stackoverflow
Solution 4 - ArraysKaranjotView Answer on Stackoverflow
Solution 5 - ArraysAtttacatView Answer on Stackoverflow
Solution 6 - ArraysGopesh BharadwajView Answer on Stackoverflow