web-dev-qa-db-fra.com

Bash Shell Script - Recherchez un drapeau et saisissez sa valeur

J'essaie de créer un script Shell conçu pour être exécuté comme suit:

script.sh -t application

Tout d'abord, dans mon script, je souhaite vérifier si le script a été exécuté avec l'indicateur -t. Par exemple, s'il a été exécuté sans le drapeau comme celui-ci, 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 réaliser à ce sujet est que $ @ saisit tous les arguments de la ligne de commande, mais je ne sais pas comment cela se rapporte aux indicateurs, ni même si c'est possible.

57
Jimmy

Vous devriez lire ce getopts tutorial.

Exemple avec le commutateur -a 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 dit greybot (getopt! = getopts): 

La commande externe getopt (1) n'est jamais sûre, sauf si vous connaissez c'est GNU getopt, vous l'appelez d'une manière spécifique à GNU, et vous vous assurez que que GETOPT_COMPATIBLE n'est pas dans l'environnement. Utilisez getopts (Shell Builtin) à la place, ou passez simplement en boucle sur les paramètres de position.

94
Gilles Quenot

Utilisez $# pour saisir le nombre d'arguments. S'il n'est pas égal à 2, le nombre d'arguments fournis est insuffisant:

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

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

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

Enfin, enregistrez $2 dans FLAG:

FLAG=$2

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

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

Performs some activity
EOF
   exit 1
}
24
Veger

Voici une interface d'argument 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

La sortie sera la suivante:

"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 arguments génériques ..__ En procédant ainsi, un utilisateur peut placer les drapeaux et les booléens n’importe où, tant qu’il conserve les arguments génériques ordre. 

Permettez-moi et maintenant vous ne jamais traiter avec bash arguemnt analyser à nouveau!

4
jozsef morrissey

Essayez shFlags - Bibliothèque avancée d’indicateurs de ligne de commande pour les scripts Unix Shell.

http://code.google.com/p/shflags/

C'est très bon et très flexible. 

TYPES DE DRAPEAU: Ceci est une liste de DEFINE _ * que vous pouvez faire. Tous les drapeaux prennent un nom, une valeur par défaut, une chaîne d'aide et un nom abrégé facultatif (un nom nom). Certains drapeaux ont d'autres arguments, décrits avec le drapeau.

DEFINE_string: prend n'importe quelle entrée et l'interprète comme une chaîne.

DEFINE_boolean: typiquement, ne prend aucun argument: dites --myflag pour définir FLAGS_myflag sur true ou --nomyflag pour définir FLAGS_myflag sur false . Alternativement, vous pouvez dire --myflag = true ou --myflag = t ou --myflag = 0 ou --myflag = false ou --myflag = f ou --myflag = 1 Passer une option a le même effet que de passer l'option une fois.

DEFINE_float: prend une entrée et l'interprète comme un nombre à virgule flottante. Comme Shell ne supporte pas les floats en soi, l'entrée est simplement validée en tant que étant une valeur en virgule flottante valide.

DEFINE_integer: prend une entrée et l'interprète comme un entier.

DRAPEAUX SPÉCIAUX: Quelques drapeaux ont une signification particulière: --help (ou -?) affiche une liste de tous les drapeaux de manière lisible par l'homme --flagfile = foo lit les drapeaux de foo. (pas encore mis en œuvre) - comme dans getopt (), termine le traitement des drapeaux

Exemple d'utilisation:

-- begin hello.sh --
 ! /bin/sh
. ./shflags
DEFINE_string name 'world' "somebody's name" n
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
echo "Hello, ${FLAGS_name}."
-- end hello.sh --

$ ./hello.sh -n Kate
Hello, Kate.

Note: J'ai pris ce texte dans la documentation de shflags

0
Anandkumar