Convert multiline string to array

Let me contribute to Sanket Parmar's answer. If you can extract string splitting and processing into a separate function, there is no need to save and restore $IFS — use local instead:

#!/bin/bash

function print_with_line_numbers {
    local IFS=$'\n'
    local lines=($1)
    local i
    for (( i=0; i<${#lines[@]}; i++ )) ; do
        echo "$i: ${lines[$i]}"
    done
}

names="Netgear
Hon Hai Precision Ind. Co.
Apple"

print_with_line_numbers "$names"

See also:

  • Setting IFS for a single statement

Bash also has a readarray builtin command, easily searchable in the man page. It uses newline (\n) as the default delimiter, and MAPFILE as the default array, so one can do just like so:

    names="Netgear
    Hon Hai Precision Ind. Co.
    Apple"

    readarray -t <<<$names

    printf "0: ${MAPFILE[0]}\n1: ${MAPFILE[1]}\n2: ${MAPFILE[2]}\n"

The -t option removes the delimiter ('\n'), so that it can be explicitly added in printf. The output is:

    0: Netgear
    1: Hon Hai Precision Ind. Co.
    2: Apple

Set IFS (Internal Field Separator). Shell uses the IFS variable to determine what the field separators are. By default, IFS is set to the space character. Change it to the newline character, as demonstrated below:

#!/bin/bash
names="Netgear
Hon Hai Precision Ind. Co.
Apple"
    
SAVEIFS=$IFS   # Save current IFS (Internal Field Separator)
IFS=$'\n'      # Change IFS to newline char
names=($names) # split the `names` string into an array by the same name
IFS=$SAVEIFS   # Restore original IFS

for (( i=0; i<${#names[@]}; i++ ))
do
    echo "$i: ${names[$i]}"
done

Output

0: Netgear
1: Hon Hai Precision Ind. Co.
2: Apple