Frontier Software

Mapfile/Readarray

An early (buggy) attempt at reading output of grep into an array looked like this:

IFS=$'\n\b' read -ra venue <<< "$(grep -Fwio -f /usr/local/share/dict/venues <<< "${location_arr["\"name\""]}")"

This was wrong because read expects a single line, and grep can output several. Another I thing I learnt was process substitution rather than overusing here strings.

mapfile -t venue < <(grep -Fwio -f /usr/local/share/dict/venues <<< "${location_arr["\"name\""]}")

This default behaviour is courtesy of an environment variable IFS (internal field separator) which comes set to space, TAB, NEWLINE. If you wanted to split a row (aka line of text) from a CSV file, you could use this combination of IFS and read.

IFS=',' read -ra col <<< "item1,item2,item3,item4"

That only temporarily changes the value of IFS for that command, and then echo "${col[0]}" returns item1, echo “${col[1]}” item2 etc.

A snag I hit with the above pattern is ShellCheck complained if I left out the -r flag (“do not allow backslashes to escape any characters”), giving warning SC2162 “read without -r will mangle backslashes.”

But including it in one of my attempts to translate JSON paths to bash array broke the code. I eventually turned to readarray, which is identical to mapfile which has a more detailed man page.

readarray -d ',' -t col <<< "item1,item2,item3,item4"

I found the above easier to understand, kept shellcheck happy while not giving weird results sometimes. That readarray and mapfile are identical, I think readarray a better mneumonic of what the command does.