[bash] Array inside associative array?

So, i have learned a cool trick of having associative arrays in bash from here, which leads in pretty clean data structures (if you're into it)...

test.sh

#!/bin/bash

declare -A themes0=(

    # Theme
    [theme_base]='org.kde.breezedark.desktop'

    # Plasma theme
    [plasma_theme]="Test-dark"
    [color_scheme]="Test Dark Blue"

    # QT theme
    [QT_theme]="breeze"
    [QT_icons]="breeze-dark"
    [QT_cursor]="Breeze_Snow"

    # GTK theme
    [GTK_theme]="Breeze-Dark"
    [GTK_icon]="${themes0[QT_icons]}"
    [GTK_iconFallback]="${themes0[GTK_icon]}"
    [GTK_cursor]="${themes0[QT_cursor]}"
)

declare -A themes1=(

    # Theme
    [theme_base]='org.kde.breeze.desktop'

    # Plasma theme
    [plasma_theme]="Test-light"
    [color_scheme]="Test Light Blue"

    # QT theme
    [QT_theme]="breeze"
    [QT_icons]="breeze"
    [QT_cursor]="breeze_cursors"

    # GTK theme
    [GTK_theme]="Breeze"
    [GTK_icon]="${themes1[QT_icons]}"
    [GTK_iconFallback]="${themes1[GTK_icon]}"
    [GTK_cursor]="${themes1[QT_cursor]}"
)

declare -n themes

main() {

    for themes in "${!themes@}";
    do
        echo "${themes[plasma_theme]}"
        echo

        for key in "${!themes[@]}";
        do
            echo "${key}:   ${themes[$key]}"
        done

        echo
    done
}

main "$@"

Now, i'd like to know how to effectively do something like that (which sadly seems to be impossible directly in current bash):

#!/bin/bash

declare -A themes0=(

    [array_in_array]=(

        # Each line (except comments and empty ones) should be parsed as array later
        "Some/Path1/file1.test" "Some/Path1/file2.test"

        # Yep, array too
        "Some/Path2/file3.test" "Some/Path3/file4.test" "Some/Path4/file5.test"
    )
)

Thoughts / tips & tricks are welcome :slight_smile:

Thoughts

declare -A themes0=(

    [plasma_theme]="test"
    [files]="Some/Path1/file1.test Some/Path1/file2.test" 
    [QT_theme]="qt"
)

for key in "${!themes0[@]}";
do
    if [[ "${key: -1}" == "s" ]]; then  # its a array (for me) !
        echo "${key}:"
        values=(${themes0[$key]})
        for v in "${values[@]}"; do echo "  - $v"; done
    else
        echo "${key}:   ${themes0[$key]}"
    fi
done

EDIT: if datas fixed, we can use conf file json(use jq) or yaml(exemple)

1 Like

its a array (for me) !

:laughing:

Nice one, but i maybe showed a little too reduced example, my bad...

array_in_array will certainly have:

  1. Some complex stuff like that:
'"$HOME/.local/share/konsole/133Matrix.colorscheme" "General" "Opacity" $(echo "scale=2; ${opacity}/100" | bc)'
  1. All paths should certainly be quoted (since it can and will have spaces), therefore simple string to array is not really possible...And your example will fail on spaced path

usually i overcome this problem with your previous advices on my question, like that:

configBluetooth=(

    # Bluetooth disable
    '"bluedevilglobalrc" "General" "enableGlobalBluetooth" false'

    # ... etc
)

for config in "${configBluetooth[@]}";
do
    configWrite "$config"
done

But when working inside another array quoting each item with ' ' is not an option it seems...

  1. I d like to have specifically multiline style of array, like in op abstract example, so that i could treat each line as array item later with something like
declare -a "config=($(printf '%s\n' "$config"))"

Wow, that's really cool!

But sadly....

In theory, can json / yaml be declared dynamically inside bash file and then parsed?
Preferably without creating temp files (although it's easy with something like that):

cat >> $HOME/data.json<<"EOL"
...
EOL

for space separator, we can change the field separator (here # for example) :

[files]="Some/Path1/file 1.test#Some/Path1/file 2.test" 
...
IFS='#' values=(${themes0[$key]})    # or IFS="\t" ...
for v in "${values[@]}"; do echo "  - $v"; done

for me "fixed" was : you dont change list in script (remove,edit...)

Oh ok...Well i do in one place now, but it can be avoided!

Yeah, you have actually sparked some thought in me about IFS...
I'm not a big fan of IFS in general, for it's somewhat destructive behavior (in case you forget to change it after some trickery)

here we not change IFS for all script but only for the line :wink:
EDIT: as a LANG=de pacman -Qi package

2 Likes

Forum kindly sponsored by