• BASH > les arguments

      TESTER LE NOMBRE D’ARGUMENTS

      $#donne le nombre d’arguments.

      Exemple : ./test.sh toto tata renvoie 2


       

      if [ $# -ne 0 ] ; then
         // blabla
      fi

      VALEUR D’UN ARGUMENT

      $0 renvoie le nom du script.

      $1 retourne la valeur du premier argument, $2 pour 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 N décale N fois la position des paramètres. Par défaut, N = 1

      Une 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

       

 

Aucun commentaire

 

Laissez un commentaire