Passer des arguments nommés en tant que tableau dans le script shell

J'ai ce code dans un outil que je suis en train de build:

while [ $# -gt 0 ]; do case "$1" in --var1=*) var1="${1#*=}" ;; --var2=*) var1="${1#*=}" ;; --var3=*) var1="${1#*=}" ;; *) printf "***************************\n * Error: Invalid argument.*\n ***************************\n" esac shift done 

J'ai plusieurs options à append, mais cinq de mes options devraient être sauvegardées en tant que arrays. Donc si j'appelle l'outil, disons de la coquille en utilisant quelque chose comme ceci:
./tool --var1="2" --var1="3" --var1="4" --var1="5" --var2="6" --var3="7"

Comment puis-je save la valeur de var1 tant que tableau? Est-ce possible? Et si oui, quelle est la meilleure façon de traiter ces arrays en termes d'efficacité si j'en ai trop?

Si sous Linux (avec les utilitaires util-linux y compris getopt installé ou celui de busybox ), vous pouvez faire:

 declare -A opt_spec var1=() var2=() var4=false unset var3 opt_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[*]}" -- "$@" ) || exit eval "set -- $parsed_opts" while [ "$#" -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 esac done echo "var1: ${var1[@]}" 

De cette façon, vous pouvez appeler votre script comme suit:

 my-script --opt1=foo --opt2 bar --opt4 -- whatever 

Et getopt fera le dur travail d'parsing, de manipulation et d'abréviations pour vous.

Vous pouvez également $opt_spec le type de la variable au lieu de le spécifier dans votre définition de tableau associatif $opt_spec :

 declare -A opt_spec var1=() var2=() var4=false unset var3 opt_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[*]}" -- "$@" ) || exit eval "set -- $parsed_opts" while [ "$#" -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 esac done echo "var1: ${var1[@]}" 

Vous pouvez append des options courtes comme:

 declare -A long_opt_spec short_opt_spec var1=() var2=() var4=false unset var3 long_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[*]}" -- "$@" ) || exit eval "set -- $parsed_opts" while [ "$#" -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 esac done echo "var1: ${var1[@]}" 

Je vous suggère de jeter un oeil à mon script shell GitHub général: utility_functions.sh . Là vous verrez une fonction appelée getArgs . Il est conçu pour associer des options et des valeurs.

Je ne colle ici que la fonction, mais cela dépend de quelques autres fonctions à l'intérieur de ce script

 ########################## # # Function name: getArgs # # Description: # This function provides the getopts functionality # while allowing the use of long operations and list of parameters. # in the case of a list of arguments for only one option, this list # will be returned as a single-space-separated list in one single ssortingng. # # Pre-reqs: # None # # Output: # GA_OPTION variable will hold the current option # GA_VALUE variable will hold the value (or list of values) associated # with the current option # # Usage: # You have to source the function in order to be able to access the GA_OPTIONS # and GA_VALUES variables # . getArgs $* # #################### function getArgs { # Variables to return the values out of the function typeset -a GA_OPTIONS typeset -a GA_VALUES # Checking for number of arguments if [[ -z $1 ]] then msgPrint -warning "No arguments found" msgPrint -info "Please call this function as follows: . getArgs \$*" exit 0 fi # Grab the dash dash=$(echo $1 | grep "-") # Looking for short (-) or long (--) options isOption=$(expr index "$dash" "-") # Initialize the counter counter=0 # Loop while there are arguments left while [[ $# -gt 0 ]] do if [[ $dash && $isOption -eq 1 ]] then (( counter+=1 )) GA_OPTIONS[$counter]=$1 shift else if [[ -z ${GA_VALUES[$counter]} ]] then GA_VALUES[$counter]=$1 else GA_VALUES[$counter]="${GA_VALUES[$counter]} $1" fi shift fi dash=$(echo $1 | grep "-") isOption=$(expr index "$dash" "-") done # Make the variables available to the main algorithm export GA_OPTIONS export GA_VALUES msgPrint -debug "Please check the GA_OPTIONS and GA_VALUES arrays for options and arguments" # Exit with success return 0 } 

Comme vous le voyez, cette fonction particulière exportera GA_OPTIONS et GA_VALUES. Seule condition pour cela est que les valeurs doivent être une list séparée par des espaces après l'option.

Vous appelez le script comme ./tool ​​–var1 2 3 4 5 –var2 = "6" –var3 = "7"

Ou utilisez simplement une logique similaire pour tenir count de vos preferences.

J'espère que cela t'aides.