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