99 votes

Bash Shell script - Vérifier la présence d'un drapeau et saisir sa valeur.

J'essaie de faire un shell script qui est conçu pour être exécuté comme ceci :

script.sh -t application

Tout d'abord, dans mon script, je veux vérifier si le script a été exécuté avec le drapeau -t. Par exemple, s'il a été exécuté sans le drapeau comme ceci, je veux qu'il se trompe :

script.sh

Deuxièmement, en supposant qu'il y ait un drapeau -t, je veux saisir la valeur et la stocker dans une variable que je peux utiliser dans mon script par exemple comme ceci :

FLAG="application"

Jusqu'à présent, le seul progrès que j'ai pu faire sur tout cela est que $@ récupère tous les arguments de la ligne de commande, mais je ne sais pas comment cela se rapporte aux drapeaux, ou si c'est même possible.

155voto

sputnick Points 31663

Vous devriez lire ceci getopts tutoriel.

Exemple avec -a interrupteur qui nécessite un argument :

#!/bin/bash

while getopts ":a:" opt; do
  case $opt in
    a)
      echo "-a was triggered, Parameter: $OPTARG" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

Comme l'a dit greybot( getopt != getopts ) :

La commande externe getopt(1) n'est jamais sûre à utiliser, sauf si vous connaître il s'agit de GNU getopt, vous l'appelez d'une manière spécifique à GNU, y vous assurez que GETOPT_COMPATIBLE n'est pas dans l'environnement. Utilisez getopts (shell builtin) à la place, ou simplement boucler sur les paramètres positionnels.

38voto

Veger Points 17657

Utilice $# pour saisir le nombre d'arguments, s'il n'est pas égal à 2, il n'y a pas assez d'arguments fournis :

if [ $# -ne 2 ]; then
   usage;
fi

Ensuite, vérifiez si $1 est égal à -t sinon un drapeau inconnu a été utilisé :

if [ "$1" != "-t" ]; then
  usage;
fi

Enfin, stockez $2 en FLAG :

FLAG=$2

Nota: usage() est une fonction montrant la syntaxe. Par exemple :

function usage {
   cat << EOF
Usage: script.sh -t <application>

Performs some activity
EOF
   exit 1
}

15voto

jozsef morrissey Points 111

Voici une interface d'arguments de commande simple et généralisée que vous pouvez coller en haut de tous vos scripts.

#!/bin/bash

declare -A flags
declare -A booleans
args=()

while [ "$1" ];
do
    arg=$1
    if [ "${1:0:1}" == "-" ]
    then
      shift
      rev=$(echo "$arg" | rev)
      if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "${rev:0:1}" == ":" ]
      then
        bool=$(echo ${arg:1} | sed s/://g)
        booleans[$bool]=true
        echo \"$bool\" is boolean
      else
        value=$1
        flags[${arg:1}]=$value
        shift
        echo \"$arg\" is flag with value \"$value\"
      fi
    else
      args+=("$arg")
      shift
      echo \"$arg\" is an arg
    fi
done

echo -e "\n"
echo booleans: ${booleans[@]}
echo flags: ${flags[@]}
echo args: ${args[@]}

echo -e "\nBoolean types:\n\tPrecedes Flag(pf): ${booleans[pf]}\n\tFinal Arg(f): ${booleans[f]}\n\tColon Terminated(Ct): ${booleans[Ct]}\n\tNot Mentioned(nm): ${boolean[nm]}"
echo -e "\nFlag: myFlag => ${flags["myFlag"]}"
echo -e "\nArgs: one: ${args[0]}, two: ${args[1]}, three: ${args[2]}"

En exécutant la commande :

bashScript.sh firstArg -pf -myFlag "my flag value" secondArg -Ct: thirdArg -f

Le résultat sera le suivant :

"firstArg" is an arg
"pf" is boolean
"-myFlag" is flag with value "my flag value"
"secondArg" is an arg
"Ct" is boolean
"thirdArg" is an arg
"f" is boolean

booleans: true true true
flags: my flag value
args: firstArg secondArg thirdArg

Boolean types:
    Precedes Flag(pf): true
    Final Arg(f): true
    Colon Terminated(Ct): true
    Not Mentioned(nm): 

Flag: myFlag => my flag value

Args: one => firstArg, two => secondArg, three => thirdArg

Fondamentalement, les arguments sont divisés en drapeaux booléens et en arguments génériques. En procédant ainsi, l'utilisateur peut placer les drapeaux et les booléens n'importe où, tant qu'il conserve les arguments génériques (s'il y en a) dans l'ordre spécifié.

Permettant à moi et maintenant à vous de ne plus jamais avoir affaire à l'analyse des arguments de bash !

Vous pouvez visualiser un script mis à jour. aquí

Cela a été extrêmement utile au cours de l'année dernière. Il peut maintenant simuler la portée en faisant précéder les variables d'un paramètre de portée.

Il suffit d'appeler le script comme suit

replace() (
  source $FUTIL_REL_DIR/commandParser.sh -scope ${FUNCNAME[0]} "$@"
  echo ${replaceFlags[f]}
  echo ${replaceBooleans[b]}
)

Il ne semble pas que j'ai implémenté l'argument scope, je ne sais pas pourquoi, je suppose que je n'en ai pas encore eu besoin.

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