Search code examples
bashgrepwindows-subsystem-for-linuxtext-parsing

grep's output is split by colon when being saved into array


I have a file with array looking like

{
    [commandA]: cmdA,
    [commandB]: cmdB,
...
}

I'd like to fetch the lines with commands by grep and store them in the bash array. But when I do

cmdFunMap=(`grep "^    \[command" myfile`)
printf '%s\n' "${cmdFunMap[@]}"

I get

[commandA]:
cmdA,
[commandB]:
cmdB,

instead of needed

[commandA]: cmdA,
[commandB]: cmdB,

I tried to match the whole line like

cmdFunMap=(`grep "^    \[command.*$" myfile`)
printf '%s\n' "${cmdFunMap[@]}"

and set IFS to \n, but the result was the same.

Bash v5.0.17(1)-release (x86_64-pc-linux-gnu), Ubuntu 20.04.3 LTS (WSL).

How can I fix this colon separation?

Upd: checked in Alpine 3.15.4, behavior is just the same.


Solution

  • You populate your array with 4 words while you'd like to populate it with 2 lines. Use mapfile, instead. By default it creates one array entry per line:

    $ mapfile -t cmdFunMap < <(grep "^    \[command" myfile)
    $ printf '%s\n' "${cmdFunMap[@]}"
        [commandA]: cmdA,
        [commandB]: cmdB,
    

    Note: don't try to pipe grep to mapfile instead of using a process substitution (<( ... )), it doesn't work and is a common misuse of pipes (and mapfile).

    Note: you can obtain the same with IFS:

    $ IFS=$'\n' cmdFunMap=(`grep "^    \[command" myfile`)
    $ printf '%s\n' "${cmdFunMap[@]}"
        [commandA]: cmdA,
        [commandB]: cmdB,
    

    The $ in IFS=$'\n' is probably the difference with what you tried, see the QUOTING section of the bash manual for the details.