505 votes

Un exemple de l'utilisation de getopts en bash

Je veux appeler myscript de cette manière :

$ ./myscript -s 45 -p any_string

ou

$ ./myscript -h  #should display help
$ ./myscript     #should display help

Mes exigences sont les suivantes :

  • getopt ici pour obtenir les arguments d'entrée
  • vérifiez que -s existe, sinon retour d'une erreur
  • vérifiez que la valeur après le -s est de 45 ou 90
  • vérifier que le -p existe et il y a une chaîne d'entrée après
  • si l'utilisateur saisit ./myscript -h ou simplement ./myscript puis afficher l'aide

J'ai essayé jusqu'à présent ce code :

#!/bin/bash
while getopts "h:s:" arg; do
  case $arg in
    h)
      echo "usage" 
      ;;
    s)
      strength=$OPTARG
      echo $strength
      ;;
  esac
done

Mais avec ce code, j'obtiens des erreurs. Comment le faire avec Bash et getopt ?

6 votes

Les options sont censées être facultatives. Si vous avez besoin de la valeur spécifiée par -s pour en faire un argument de position : ./myscript 45 anystring .

1 votes

@chepner $./myscript -s 45 -p any_string

2 votes

C'est bien si -p est en fait une option (c'est-à-dire que votre programme peut continuer s'il n'est pas présent). Dans ce cas, ./myscript 45 -p any_string . (Je pense que getopt peut gérer des options mixtes et des arguments positionnels, alors que la méthode bash commande intégrée getopts exige que tous les arguments positionnels soient placés après les options).

12voto

Ciro Santilli Points 3341

Exemple de POSIX 7

Il est également intéressant de vérifier l'exemple de la norme : http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html

aflag=
bflag=
while getopts ab: name
do
    case $name in
    a)    aflag=1;;
    b)    bflag=1
          bval="$OPTARG";;
    ?)   printf "Usage: %s: [-a] [-b value] args\n" $0
          exit 2;;
    esac
done
if [ ! -z "$aflag" ]; then
    printf "Option -a specified\n"
fi
if [ ! -z "$bflag" ]; then
    printf 'Option -b "%s" specified\n' "$bval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"

Et ensuite nous pourrons l'essayer :

$ sh a.sh
Remaining arguments are: 
$ sh a.sh -a
Option -a specified
Remaining arguments are: 
$ sh a.sh -b
No arg for -b option
Usage: a.sh: [-a] [-b value] args
$ sh a.sh -b myval
Option -b "myval" specified
Remaining arguments are: 
$ sh a.sh -a -b myval
Option -a specified
Option -b "myval" specified
Remaining arguments are: 
$ sh a.sh remain
Remaining arguments are: remain
$ sh a.sh -- -a remain
Remaining arguments are: -a remain

Testé dans Ubuntu 17.10, sh est dash 0.5.8.

6voto

Twoez Points 235

"getops" et "getopt" sont très limités. Alors que "getopt" est suggéré de ne pas être utilisé du tout, il offre des options longues. Alors que "getopts" ne permet que des options à un seul caractère comme "-a" "-b". Il y a quelques autres inconvénients à utiliser l'un ou l'autre.

J'ai donc écrit un petit script qui remplace "getopts" et "getopt". C'est un début, il pourrait probablement être beaucoup amélioré.

Mise à jour 08-04-2020 : J'ai ajouté le support des traits d'union, par exemple "--package-name".

Utilisation : "./script.sh package install --package "nom avec espace" --build --archive"

# Example:
# parseArguments "${@}"
# echo "${ARG_0}" -> package
# echo "${ARG_1}" -> install
# echo "${ARG_PACKAGE}" -> "name with space"
# echo "${ARG_BUILD}" -> 1 (true)
# echo "${ARG_ARCHIVE}" -> 1 (true)
function parseArguments() {
  PREVIOUS_ITEM=''
  COUNT=0
  for CURRENT_ITEM in "${@}"
  do
    if [[ ${CURRENT_ITEM} == "--"* ]]; then
      printf -v "ARG_$(formatArgument "${CURRENT_ITEM}")" "%s" "1" # could set this to empty string and check with [ -z "${ARG_ITEM-x}" ] if it's set, but empty.
    else
      if [[ $PREVIOUS_ITEM == "--"* ]]; then
        printf -v "ARG_$(formatArgument "${PREVIOUS_ITEM}")" "%s" "${CURRENT_ITEM}"
      else
        printf -v "ARG_${COUNT}" "%s" "${CURRENT_ITEM}"
      fi
    fi

    PREVIOUS_ITEM="${CURRENT_ITEM}"
    (( COUNT++ ))
  done
}

# Format argument.
function formatArgument() {
  ARGUMENT="${1^^}" # Capitalize.
  ARGUMENT="${ARGUMENT/--/}" # Remove "--".
  ARGUMENT="${ARGUMENT//-/_}" # Replace "-" with "_".
  echo "${ARGUMENT}"
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X