Home > Blockchain >  How to create an associate array with value of a list of items in bash
How to create an associate array with value of a list of items in bash

Time:02-15

I would like to create such a associated array in bash:

myarr = {
    'key1' : ["command_name", "command name with arguments"],
    'key2' : ["command_name", "command name with arguments"],
}

The reason I want to do the above is so that I can pass a key to the script and then do something like this:

  • Use the key to index into the associative array
  • Use some tool to check whether the application given by command_name is open
  • If the window is not open, lunch the application given by command name with arguments

Such a task is trivial in a popular programming language, but it doesn't seem to be as trivial in bash.

EDIT

I'd like to be able to create something like this:

declare -A array=(
    [c]=("code" "code")
    [e]=("dolphin" "XDG_CURRENT_DESKTOP=KDE dolphin")
    [n]=("nvim" "kitty nvim")
)

CodePudding user response:

Storing bash commands and their arguments in variables is not recommended. But if you really need this it would be better to store the command names in an associative array and the full commands in as many indexed arrays, named like your keys if your keys are valid bash variable names.

If your bash is recent enough you can use namerefs. And so, instead of an associative array we could also use namerefs for the command names.

As you want to set bash variables in the command's context we cannot execute them with "$cmd", this would not work for variable assignments. The following uses eval, which is extremely risky, especially if you do not fully control the inputs. A better solution, but more complicated, would be to use other arrays for the execution environment, declare functions to limit the scope of variables and/or restore them afterwards, use eval only in last resort and only after sanitizing its parameters (printf '%q')... Anyway, you have been warned.

Example where the key is stored in bash variable k, and the command is the second of your own example, plus some dummy arguments:

k="e"
# add a new command with key "$k"
declare -n cmd="${k}_cmd"
cmd="dolphin"
declare -n lcmd="${k}_lcmd"
lcmd=("XDG_CURRENT_DESKTOP=KDE" "dolphin" "arg1" "arg2" "arg 3")
...
# launch command with key "$k"
declare -n cmd="${k}_cmd"
declare -n lcmd="${k}_lcmd"
eval "$lcmd"

Demo with key foo, command ls and arguments -i -I "foo*":

$ k="foo"
$ declare -n cmd="${k}_cmd"
$ cmd="ls"
$ declare -n lcmd="${k}_lcmd"
$ lcmd=("XDG_CURRENT_DESKTOP=KDE" "ls" "-i" "-I "foo*"")
$ touch a b c d foobar
$ eval "${lcmd[@]}"
80966495 a  80966496 b  80966497 c  80966498 d
  • Related