web-dev-qa-db-fra.com

Comment gérer les commutateurs dans un script shell?

Y a-t-il des outils intégrés qui reconnaîtront -x et --xxxx En tant que commutateurs, et non arguments, ou devez-vous passer à travers toutes les variables d'entrée, tester les tirets, puis analyser les arguments par la suite?

17
user394

Je suppose que vous utilisez Bash ou similaire. Un exemple:

all=false
long=false

while getopts ":hal" option; do
  case $option in
    h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;;
    a) all=true ;;
    l) long=true ;;
    ?) echo "error: option -$OPTARG is not implemented"; exit ;;
  esac
done

# remove the options from the positional parameters
shift $(( OPTIND - 1 ))

ls_opts=()
$all && ls_opts+=( -a )
$long && ls_opts+=( -l )

# now, do it
ls "${ls_opts[@]}" "$@"
22
glenn jackman

Vous devez écrire un cycle pour analyser les paramètres. En effet, vous pouvez utiliser la commande getopts pour le faire facilement.

Ceci est un exemple simple de getopts Page manuelle:

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" "$*"
5
andcoz

J'ai récemment écrit un script pour travailler polyvalent et autorisé pour plusieurs types de commutateurs dans n'importe quel ordre. Je ne peux pas divulguer le script complet pour des raisons juridiques évidentes (sans oublier que je ne l'ai pas avec moi pour le moment), mais voici la viande de celle-ci .. Vous pouvez la mettre dans un sous-programme et l'appeler à la fin de votre script:

options () {

    if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist
        while (( "$#" )); do  # process ALL arguments
            if [ "$1" = ^-t$ ]; then # -t short for "test"
                # do something here THEN shift the argument
                # shift removes it from $@ and reduces $# by
                # one if you supply no argument
                shift

            # we can also process multiple arguments at once
            Elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments
                # do something more then remove them ALL from the arg list    
                shift 3
            else
                echo "No matching arguments!"
                echo "Usage: [script options list here]"
            fi
        done
    else
        echo "Usage: [script options list here]"
        exit 0
    fi
}

options "$@" # run options and loop through/process ALL arguments

Je recommande de limiter votre script Bash à moins de 400 lignes/15k caractères; Mon script susmentionné a dépassé cette taille et est devenu grandement difficile de travailler. J'ai commencé à y réécrire à Perl, ce qui est beaucoup mieux adapté à la tâche. Gardez cela à l'esprit lorsque vous travaillez sur vos scripts à bash. Bash est idéal pour les petits scripts et les tinantaines, mais quelque chose de plus complexe et vous feriez mieux de l'écrire à Perl.

Note, je n'ai pas testé ce qui précède, cela ne fonctionne probablement pas, mais vous obtenez l'idée générale de celle-ci.

2
laebshade