Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to read multiline input into an array in bash shell script

Tags:

arrays

bash

Is this a correct way to read multi line input into an array in bash?

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

I put this line into a script and I tried to read multiple input by hitting return key after each line but the script keeps on taking the input and does not print the elements of the array by coming to the second line, when I press ctrl C at the input console the script terminates. Please suggest if that the correct way to read multi line input from the command line?

like image 335
Vicky Avatar asked Dec 27 '16 12:12

Vicky


1 Answers

Several points to address:

First, don't use Ctrl-C but Ctrl-D to end the input: Ctrl-C will break the script (it sends the SIGINT signal), whereas Ctrl-D is EOF (end of transmission).

To print the array, one field per line, use

printf '%s\n' "${arr[@]}"

Now, the bad way:

arr=( $(cat) )
printf '%s\n' "${arr[@]}"

This is bad since it's subject to word splitting and pathname expansion: try to enter hello word or * and you'll see bad things happen.

To achieve what you want: with Bash≥4 you can use mapfile as follows:

mapfile -t arr
printf '%s\n' "${arr[@]}"

or, with legacy Bash, you can use a loop:

arr=()
while IFS= read -r l; do
    arr+=( "$l" )
done
printf '%s\n' "${arr[@]}"

If you want to print each line as it's typed, it's probably easier to use the loop version:

arr=()
while IFS= read -r l; do
    printf '%s\n' "$l"
    arr+=( "$l" )
done

If you're feeling adventurous, you can use mapfile's callback like so:

cb() { printf '%s\n' "$2"; }
mapfile -t -c1 -C cb arr
like image 91
gniourf_gniourf Avatar answered Sep 17 '22 12:09

gniourf_gniourf