Search code examples
bashmacosunixvectorzsh

On a mac, bash scripting shows uncertain behaviour w associative array (dictionaries)


First off (mac uses this % for what I am used to be ~$ ad input in the terminal, therefore I am going to use mac convention to indicate command launched:

~% echo $SHELL
/bin/zsh
~% zsh --version
zsh 5.9 (x86_64-apple-darwin22.0)

The test.sh (line numbers vim-style for convenient reading):

    1 #!/bin/bash
    2 # 
    3 declare -A myvector
    4 echo "wut?"

I am assuming zsh (which I don't know how to use) runs bash (I am born with it :_), but

~% chmod u+x ./test.sh
~% ./test.sh
./test.sh: line 3: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
wut?

Then executing:

~% . ./test.sh
wut?

I assume the . is zsh launching the script and without its bash.

I checked various questions on how to use declare, typeset in both zsh and bash from stackoverflow in unix.stackoverflow.com and askdifferent.stackoverflow.com

The problem is man bash and man zshbuiltins give all incogruent and nonworking way to use associative array.

Why I can't declare vector and use bash way (AND also as man zshbuiltins say I could).

The following doesn't work in no way possible How to iterate over associative arrays in Bash

So changing it to

    ...
    3 declare -a myvector
    ...

so also initializing the vector with does not work

    myvector=(a 0 b 0 c 0)

nor

    myvector=("a" 0 "b" 0 "c" 0)

I am really at a loss here... should I just quit C.S. for another 5 years xD?


Solution

  • I am assuming zsh (which I don't know how to use) runs bash

    No, zsh and bash are 2 completely different shells, each with their own syntax, builtin commands, etc.

    mac uses this % for what I am used to be ~$

    Not exactly, that's just whatever string your PS1 variable is set to in your .profile (or .bash_profile or .zsh_profile, whichever you use) or the system .profile by default. Type PS1='fluffy bunny ' on the command line and hit enter to see it changed.

    I don't know zsh but try this:

    $ cat tst.sh
    #!/usr/bin/env bash
    
    declare -A assoc_arr=( ['foo']='bar', ['this']='that other thing' )
    declare -p assoc_arr
    
    echo ""
    
    declare -a index_arr=( 'twas the' 'best of times' )
    declare -p index_arr
    

    $ ./tst.sh
    declare -A assoc_arr=([foo]="bar," [this]="that other thing" )
    
    declare -a index_arr=([0]="twas the" [1]="best of times")
    

    That will run your script using the first version of bash found in your PATH regardless of whether it's called from zsh or bash or any other shell. If the above doesn't work for you then you have some version of bash that doesn't support declare -A first in your PATH.

    MacOS comes with zsh as the default login shell and a very old version of bash to avoid some licensing issues, so either learn zsh or, if you're going to use bash, you should install a newer version (google "use bash on Mac" or similar).