20

How could I read user input as an array in the bash shell?

2
  • I'm presuming you want to read from stdin? My answer will also work with execution like cat war_and_peace.txt | ./array_test.sh. Mar 6, 2011 at 7:48
  • Or simply ./array_test.sh < war_and_peace.txt. May 11, 2015 at 18:13

5 Answers 5

18

Here's one way to do it:

while read line
do
    my_array=("${my_array[@]}" $line)
done

echo ${my_array[@]}

If you just run it, it will keep reading from standard-input until you hit Ctrl+D (EOF). Afterwards, the lines you entered will be in my_array. Some may find this code confusing. The body of the loop basically says my_array = my_array + element.

Some interesting pieces of documentation:

2
  • 4
    read -r is quite useful/important sometimes... Stefano's link to the "read builtin manpage" explains its purpose...(to prevent backslash interpretation).
    – Peter.O
    Mar 9, 2011 at 5:04
  • Not very useful in a script wanting user input
    – Sruli
    Jun 2, 2020 at 15:30
16

Read it using this:

read -a arr

And for printing, use:

for elem in ${arr[@]}
do 
  echo $elem
done
4

And one that doesn't recreate the array each time (though requires bash 3.1 or newer):

array=()
while IFS= read -r -p "Next item (end with an empty line): " line; do
    [[ $line ]] || break  # break if line is empty
    array+=("$line")
done

printf '%s\n' "Items read:"
printf '  «%s»\n' "${array[@]}"

See http://mywiki.wooledge.org/BashFAQ/001 for more.

And as always, to avoid writing bugs read http://mywiki.wooledge.org/BashGuide and avoid the tldp-guides like the Advanced bash scripting guide.

1
  • Nice links... Thanks for pointing out the IFS issue. Without nulling it, 'read' sripts all leading and trailing whitespace... and of course the -r too...
    – Peter.O
    Mar 9, 2011 at 5:20
1

How about this one-liner ;)

arr=( $(cat -) )
echo ${arr[@]}

Edit:

In bash,

arr=(val1 val2 ...)

is the way of assigning to an array. Using it in conjunction with command substitution, you can read in arrays from pipeline which is not possible to use read to accomplish this in a straight-forward manner:

echo -e "a\nb" | read -a arr
echo ${arr[@]}

You will find that it output nothing due to the fact that read does nothing when stdin is a pipe since a pipeline may be run in a subshell so that the variable may not be usable at all.

Using the way suggested by this answer:

arr=(`echo -e "a\nb"`)
echo ${arr[@]}

It gives a b which is way simpler and more straight-forward than any workaround given by the answers of Read values into a shell variable from a pipe and in bash read after a pipe is not setting values.

3
  • 1
    did you test it ?
    – cmak.fr
    Mar 9, 2019 at 8:39
  • @cmak.fr yes it works for me
    – Quark
    Mar 10, 2019 at 5:59
  • @Melebius I have appended an explanation of it and the advantage of this one-liner.
    – JiaHao Xu
    Aug 19, 2019 at 6:45
1
#!/bin/bash

read line 
list=(${line})

for i in ${list[@]};do
  echo $i
done

OUTPUT

./list-input.sh
banna apple pie
banna
apple
pie

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.