I have this code in a tool I am currently building:   while [ $# -gt 0 ]; do  case $1 in    --var1=*)      var1=${1#*=}      ;;    --var2=*)      var1=${1#*=}      ;;    --var3=*)      var1=${1#*=}      ;;    *)      printf ***************************\n              * Error: Invalid argument.*\n              ***************************\n  esac  shiftdoneI have many options to add, but five of my options should be saved as arrays. So if I call the tool, let's say from the shell using something like this:./tool --var1=2 --var1=3 --var1=4 --var1=5 --var2=6 --var3=7 How can I save the value of var1 as an array? Is that possible? And, if so, what is the best way to deal with these arrays in terms of efficiency if I have too many of them?.
Passing named arguments as array in shell script
bash;shell;shell script
If on Linux (with the util-linux utilities including getopt installed, or the one from busybox), you can do:declare -A opt_specvar1=() var2=() var4=falseunset var3opt_spec=(  [opt1:]='var1()' # opt with argument, array variable  [opt2:]='var2()' # ditto  [opt3:]='var3'   # opt with argument, scalar variable  [opt4]='var4'    # boolean opt without argument)parsed_opts=$(  IFS=,  getopt -o + -l ${!opt_spec[*]} -- $@) || exiteval set -- $parsed_optswhile [ $# -gt 0 ]; do  o=$1; shift  case $o in    (--) break;;    (--*)      o=${o#--}      if ((${opt_spec[$o]+1})); then # opt without argument        eval ${opt_spec[$o]}=true      else        o=$o:        case ${opt_spec[$o]} in          (*'()') eval ${opt_spec[$o]%??}+=(\\$1\);;          (*) eval ${opt_spec[$o]}=\$1        esac        shift      fi  esacdoneecho var1: ${var1[@]}That way, you can call your script as:my-script --opt1=foo --opt2 bar --opt4 -- whateverAnd getopt will do the hard work of parsing it, handling -- and abbreviations for you.Alternatively, you could rely on the type of the variable instead of specifying it in your $opt_spec associative array definition:declare -A opt_specvar1=() var2=() var4=falseunset var3opt_spec=(  [opt1:]=var1   # opt with argument  [opt2:]=var2   # ditto  [opt3:]=var3   # ditto  [opt4]=var4    # boolean opt without argument)parsed_opts=$(  IFS=,  getopt -o + -l ${!opt_spec[*]} -- $@) || exiteval set -- $parsed_optswhile [ $# -gt 0 ]; do  o=$1; shift  case $o in    (--) break;;    (--*)      o=${o#--}      if ((${opt_spec[$o]+1})); then # opt without argument        eval ${opt_spec[$o]}=true      else        o=$o:        case $(declare -p ${opt_spec[$o]} 2> /dev/null) in          (declare -a*) eval ${opt_spec[$o]}+=(\\$1\);;          (*) eval ${opt_spec[$o]}=\$1        esac        shift      fi  esacdoneecho var1: ${var1[@]}You can add short options like:declare -A long_opt_spec short_opt_specvar1=() var2=() var4=falseunset var3long_opt_spec=(  [opt1:]=var1   # opt with argument  [opt2:]=var2   # ditto  [opt3:]=var3   # ditto  [opt4]=var4    # boolean opt without argument)short_opt_spec=(  [a:]=var1  [b:]=var2  [c]=var3  [d]=var4)parsed_opts=$(  IFS=; short_opts=${!short_opt_spec[*]}  IFS=,  getopt -o +$short_opts -l ${!long_opt_spec[*]} -- $@) || exiteval set -- $parsed_optswhile [ $# -gt 0 ]; do  o=$1; shift  case $o in    (--) break;;    (--*)      o=${o#--}      if ((${long_opt_spec[$o]+1})); then # opt without argument        eval ${long_opt_spec[$o]}=true      else        o=$o:        case $(declare -p ${long_opt_spec[$o]} 2> /dev/null) in          (declare -a*) eval ${long_opt_spec[$o]}+=(\\$1\);;          (*) eval ${long_opt_spec[$o]}=\$1        esac        shift      fi;;    (-*)      o=${o#-}      if ((${short_opt_spec[$o]+1})); then # opt without argument        eval ${short_opt_spec[$o]}=true      else        o=$o:        case $(declare -p ${short_opt_spec[$o]} 2> /dev/null) in          (declare -a*) eval ${short_opt_spec[$o]}+=(\\$1\);;          (*) eval ${short_opt_spec[$o]}=\$1        esac        shift      fi  esacdoneecho var1: ${var1[@]}