2017-07-08 7 views
0

Les getopts Bash doivent permettre aux options et arguments de ne pas dépendre de la position, comme indiqué dans tutorials et docs.bash getopts ignore les options sauf si elles sont spécifiées d'une certaine manière

L'extrait de code suivant peut recevoir deux options:

  • une option de débogage -d qui nécessite un argument
  • une option -f force de , sans arguments.

Je vois le comportement étrange que seule la première option répertoriée est traitée correctement.

#!/bin/bash 

## Defaults 
DEBUG=INFO 
forceOption=FALSE 

## Usage 
printUsage() { 
    echo " "  
    echo "USAGE: $0 [-d <DEBUG_LEVEL>] [ -f ]" 
    echo " "  
    exit 1 
} 

# 
## Manage options before start 
# 

while getopts "hfd:" OPT 
do 
    case $OPT in 
     h) printUsage ;; 
     f) forceOption="TRUE" ;; 
     d) debugLevel="$OPTARG" ;; 
     *) printUsage ;;  
    esac 
    shift `expr $OPTIND - 1` 
done 

if [ -n "$debugLevel" ] ; then 
    DEBUG="$debugLevel" 
fi 

echo "DEBUG : $DEBUG" 
echo "Force : $forceOption" 

Vous pouvez voir le comportement défectueux ci-dessous:

[rgulia$ ~] ./getopts.sh -d WARNING -f 
DEBUG : WARNING 
Force : FALSE 
[rgulia$ ~] ./getopts.sh -f -d WARNING 
DEBUG : INFO 
Force : TRUE 

Le code correctement lorsque les parse options sont utilisées séparément ou si -f précède -d dans la liste des options et ils sont attachés les uns aux autres

[rgulia$ ~] ./getopts.sh -f 
DEBUG : INFO 
Force : TRUE 
[rgulia$ ~] ./getopts.sh -d WARNING 
DEBUG : WARNING 
Force : FALSE 
[rgulia$ ~] ./getopts.sh -fd WARNING 
DEBUG : WARNING 
Force : TRUE 

Mon impression est que la boucle sort trop tôt b parce qu'elle ne parvient pas à calculer correctement OPTIND quand une option est passée à un argument.

J'ai fait quelques tracés avec des instructions printf pour les valeurs de OPT, OPTARG et OPTIND confirme une telle théorie, mais je ne comprends toujours pas pourquoi cela se passe et comment le réparer.

Des suggestions?

Répondre

1

Déconnecte la boucle. OPTIND est un index absolu dans le vecteur arg original. Faites le changement une fois après la boucle

+0

Vous avez raison! Ça marche. Je pense que j'avais mal compris la signification de OPTIND tout le long. Donc, getopts garde trace de l'option et des arguments lus dans la boucle et la décrémentation d'OPTIND est seulement de faire savoir à ce shell combien d'arguments sont restés dans le vecteur arg une fois que -d et -f sont traités, non? – rgulia

+0

oui. Personnellement, j'ai arrêté d'utiliser le style getopts pour les arguments. Il a été conçu pour être laconique (à un moment où "copier" était trop long, d'où "cp") et quand la plupart des autres OS majeurs (MSDOS, VMS, RSTS) utilisaient 'command/option = value ..." ' # mais Unix a utilisé "/" dans les chemins, donc il est passé à "-o value" Il est ridiculement facile (dans les scripts et les programmes) de balayer les args [] pour les chaînes de la forme 'option = value' ... utiliser également les paramètres par défaut définis dans l'environnement My 2c – Mischa

+0

Merci beaucoup pour l'explication! – rgulia