-
BASH > les arguments
TESTER LE NOMBRE D’ARGUMENTS
$#donne le nombre d’arguments.Exemple :
./test.sh toto tatarenvoie 2
if [ $# -ne 0 ] ; then // blabla fi
VALEUR D’UN ARGUMENT
$0renvoie le nom du script.$1retourne la valeur du premier argument,$2pour le deuxième, etc../test.sh toto tata $0 -> test.sh $1 -> toto $2 -> tata
Accéder au 10ème argument
script.sh un deux trois quatre cinq six sept huit neuf dix onze echo $10 → un0 echo ${10} → dix
TOUS LES ARGUMENTS
"$*"considère l’ensemble des paramètres comme une unique chaîne de caractères"$1 $2 … ""$@"produit autant de chaînes que de paramètres"$1″ "$2″ …DÉCALER LES ARGUMENTS
shift Ndécale N fois la position des paramètres. Par défaut, N = 1Une fois le décalage effectué, le paramètre # est mis à jour.
script.sh toto tata titi echo $1 → toto shift echo $1 → tata
script.sh toto tata titi echo $1 → toto shift 2 echo $1 → titi
PARAMÈTRE PAR DÉFAUT
Si on ne donne pas de paramètre à un script alors qu’il en faut un :
Donner une valeur par défaut au 1er paramètre :
: ${1:=toto}Afficher un message d’erreur :
: ${1:?"Erreur: argument manquant"}Passer des arguments nommés
mon_script.sh -p_out '/some/path' -arg_1 '5'
#!/bin/bash while getopts ":a:p:" opt; do case $opt in a) arg_1="$OPTARG" ;; p) p_out="$OPTARG" ;; \?) echo "Option non valide: -$OPTARG" >&2 exit 1 ;; esac case $OPTARG in -*) echo "L'option $opt doit avoir une valeur" exit 1 ;; esac done printf "Argument p_out is %s\n" "$p_out" printf "Argument arg_1 is %s\n" "$arg_1"
Then you can do
$ ./my_script -p '/some/path' -a5 Argument p_out is /some/path Argument arg_1 is 5
Voir Small getopts tutorial or you can type help getopts at the shell prompt.
This is not a parser for positioned arguments, is for key=value aa=bb arguments;
for ARG in "$@" ; do KEY=$(echo $ARG | cut -f1 -d=) KEY_LENGTH=${#KEY} VALUE="${ARG:$KEY_LENGTH+1}" export "$KEY"="$VALUE" done # use here your expected variables echo "STEPS = $STEPS" echo "REPOSITORY_NAME = $REPOSITORY_NAME" echo "EXTRA_VALUES = $EXTRA_VALUES"
Usage
bash args_shell_parser.sh STEPS="ABC" REPOSITORY_NAME="stackexchange" EXTRA_VALUES="KEY1=VALUE1 KEY2=VALUE2"
Console result:
STEPS = ABC REPOSITORY_NAME = stackexchange EXTRA_VALUES = KEY1=VALUE1 KEY2=VALUE2
Features:
>values could have spaces.
>It handles complex cases, when the argument value contains "=" sign
I stole this from drupal.org, but you could do something like this:
while [ $# -gt 0 ]; do case "$1" in --p_out=*) p_out="${1#*=}" ;; --arg_1=*) arg_1="${1#*=}" ;; *) printf "*** Error: Invalid argument. ***\n" exit 1 esac shift done
The probably closest syntax to that is:
p_out='/some/path' arg_1='5' my_script
I just came up with this script
while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then v="${1/--/}" declare $v="$2" fi shift done
pass it like my_script --p_out /some/path --arg_1 5 and then in the script you can use $arg_1 and $p_out.
This answer was initially an edit of @cdmo’s answer (thanks to @Milkncookiez’s comment also!), that got rejected as expected.
When using the variables, one can make sure that they have a default value set by using "${p_out:-"default value"}" for example.
From 3.5.3 Shell Parameter Expansion of the GNU Bash manual:
${parameter:-word}If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
#!/bin/bash while [ $# -gt 0 ]; do case "$1" in -p|-p_out|--p_out) p_out="$2" ;; -a|-arg_1|--arg_1) arg_1="$2" ;; *) printf "*** Error: Invalid argument. ***\n" exit 1 esac shift shift done echo "--- Sans default values ---" echo "p_out: ${p_out}" echo "arg_1: ${arg_1}" echo "--- Avec default values:" echo "p_out: ${p_out:-\"27\"}" echo "arg_1: ${arg_1:-\"smarties cereal\"}"
The below invocations are all equivalent:
$ ./my-script.sh -a "lofa" -p "miez" $ ./my-script.sh -arg_1 "lofa" --p_out "miez" $ ./my-script.sh --arg_1 "lofa" -p "miez"
I found the solution from cdmo the best, because it is not only limited to a single letter. With a slight adjustment it will consume either whitespace separated arguments like --url www.example.com and those with an assignment like, for example the synonym parameter -u=www.example.com. Even flag arguments can be parsed:
while [ $# -gt 0 ]; do case "$1" in --url*|-u*) if [[ "$1" != *=* ]]; then shift; fi # Value is next arg if no `=` URL="${1#*=}" ;; --file*|-f*) if [[ "$1" != *=* ]]; then shift; fi FILE="${1#*=}" ;; --help|-h) printf "Meaningful help message" # Flag argument exit 0 ;; *) >&2 printf "Error: Invalid argument\n" exit 1 ;; esac shift done
I made a combination of some approaches recommended here. In my case, I need a script that could handle arguments in this format: --arg1=test So I used the following:
args=() for argument in "$@" do key=$(echo $argument | cut -f1 -d=) value=$(echo $argument | cut -f2 -d=) if [[ $key == *"--"* ]]; then v="${key/--/}" declare $v="${value}" fi done args+=( '--local_dir' ${local_dir}) args+=( '--format' ${format}) python3 ./test.py "${args[@]}"
You can see that I added the arguments together to call a python script with those arguments: test_script.sh --local_dir=test --format=other
Thanks to Shahzad Malik and JRichardsz, for the guide to join the two approaches.
I have just made this one. It doesn’t require "=" and supports non-valued parameters. Mind the need of additional shift commands for valued parameters.
#!/bin/bash if [ $# -eq 0 ]; then printf "Utilizacao:\n" printf "$0 [[--imagem_inicial|-i] <tag_inicial>] [[--imagem_final|-f] <tag_final>] [--verbose|-v]\n" exit 1 fi while [ $# -gt 0 ]; do case "$1" in --imagem_inicial|-i) export tag_imagem_inicial="${2}" shift ;; --imagem_final|-f) export tag_imagem_final="${2}" shift ;; --verbose|-v) export verbose_option=1 ;; *) printf "ERRO: Parametros invalidos\n" printf "Execute sem parametros para a sintaxe.\n" exit 1 esac shift done echo tag_imagem_inicial=${tag_imagem_inicial} echo tag_imagem_final=${tag_imagem_final}
My solution is based on that of JRichardsz, but fixing a few issues and adding more transparency about what’s actually going on − I’m not a fan of "copy this random code that you don’t understand, and run it on your personal computer. I swear it’s safe" :P
for argument in "$@" do key=$(echo $argument | cut --fields 1 --delimiter='=') value=$(echo $argument | cut --fields 2 --delimiter='=') case "$key" in "wallet") wallet="$value" ;; "network") network="$value" ;; *) esac done echo "We'll be using wallet $wallet and network $network"
Invoking this script can be done as:
myScript.sh wallet=myWallet.json network=https://granadanet.smartpy.io
—
EXEMPLE DE SCRIPT
copier un fichier / dossier
#!/bin/bash for argument in "$@" ; do key=$(echo $argument | cut --fields 1 --delimiter='=') value=$(echo $argument | cut --fields 2 --delimiter='=') case "$key" in "d") d="$value" ;; # directory "b") b="$value" ;; # basename "w") w="$value" ;; # basename without extension "x") x="$value" ;; # extension *) esac done # Switch Directory cd "$d" # Determine Extension if [[ -z "$x" ]] ; then extn=$null else extn=".$x" fi # Determine Copy Count n=1 out="$w-copy$n$extn" while [ -e "$out" ]; do n=$(( n + 1 )) out="$w-copy$n$extn" done # Construct Command if [ -d "$b" ] ; then command=(/usr/bin/rsync -ar "$b/" "$out") else command=(/usr/bin/rsync -a "$b" "$out") fi # DEBUG: Display Command #zenity --info --text="${command[*]//"/\\"/}" --width=600 # Execute Command "${command[@]}" # Handle Command Error res=$? if [[ $res != 0 ]] ; then zenity --error --text="Duplication of $b failed (not root?)\n- base: $b\n- ext: $x\n- dir: $d" --width=600 fi
—