How to read a multi-line string into a regular bash "indexed" array
The Bash shellcheck
static code analyzer and checker tool recommends in SC2206 to use read -r
or mapfile
. Their mapfile
example is complete, but their read
example only covers the case of splitting a string by spaces, not newlines, so I learned the complete form of the read
command for this purpose from @Toni Dietze's comment here.
So, here is how to use both to split a string by newlines. Note that <<<
is called a "herestring". It is similar to <<
which is a "heredoc", and <
which reads in a file:
# split the multiline string stored in variable `var` by newlines, and
# store it into array `myarray`
# Option 1
# - this technique will KEEP empty lines as elements in the array!
# ie: you may end up with some elements being **empty strings**!
mapfile -t myarray <<< "$multiline_string"
# OR: Option 2 [my preference]
# - this technique will NOT keep empty lines as elements in the array!
# ie: you will NOT end up with any elements which are empty strings!
IFS=$'\n' read -r -d '' -a myarray <<< "$multiline_string"
There is also a 3rd technique I use the most, which is not necessarily recommended by shellcheck, but which is fine if you use it correctly, and which is far more readable than either of the options above. I use it in many scripts in my eRCaGuy_dotfiles/useful_scripts
directory here. Clone that repo and run grep -rn "IFS"
in it to find all places where I use that technique.
See here for where I first learned this: Answer here by @Sanket Parmar: Convert multiline string to array.
Here it is:
# Option 3 [not necessarily recommended by shellcheck perhaps, since you must
# NOT use quotes around the right-hand variable, but it is **much
# easier to read**, and one I very commonly use!]
#
# Convert any multi-line string to an "indexed array" of elements:
#
# See:
# 1. "eRCaGuy_dotfiles/useful_scripts/find_and_replace.sh" for an example
# of this.
# 1. *****where I first learned it: https://mcmap.net/q/12399/-convert-multiline-string-to-array-duplicate
SAVEIFS=$IFS # Save current IFS (Internal Field Separator).
IFS=$'\n' # Change IFS (Internal Field Separator) to the newline char.
# Split a long string into a bash "indexed array" (via the parenthesis),
# separating by IFS (newline chars); notice that you must intentionally NOT use
# quotes around the parenthesis and variable here for this to work!
myarray=($multiline_string)
IFS=$SAVEIFS # Restore IFS
See also:
- Where I learned my "Option 3" above: Answer here by @Sanket Parmar: Convert multiline string to array
- Read file into array with empty lines
- An example where I read a bash multi-line string into a bash array using the
read
cmd: Find all files in a directory that are not directories themselves
read
by line loop. – Perfumery