skip to Main Content

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 '%sn' "${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 '%sn' "${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.

2

Answers


  1. Alright, mate, let’s tackle this colon conundrum. It seems like your grep output is playing tricks on you, and we need to whip it into shape. Here’s a fix for ya:

    # Use grep with the -o option to print only the matched part of the line
    # We'll also match the part after the colon to get the full command
    cmdFunMap=(`grep -o "^    [command[^:]*: [^,]*" myfile`)
    printf '%sn' "${cmdFunMap[@]}"
    

    This should give you the output you’re after:

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

    It’s all about using that -o option to snatch just the parts you need. Good luck with your bash array, and don’t let those tricky colons get the best of you! And if you run into any more snags, just remember, we Aussies are used to dealing with creatures that can be a bit unpredictable, like kangaroos and drop bears. Cheers!

    Login or Signup to reply.
  2. 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 '%sn' "${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 '%sn' "${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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search