2017-09-21 6 views
0

Je veux utiliser à la fois getopts et les paramètres de position, mais si je passe dans un paramètre positionnel au programme, les getopts se perdent.Comment combiner les getopts et les paramètres de position dans bash?

directory=$1 

while getopts l: flag; do 
    case "$flag" in 
    l) level=$OPTARG;; 
    esac 
done 

if [ -n "$level" ]; then 
    echo "Level exist!" 
else 
    echo "Level doesn't exist!" 
fi 

Alors, quand je lance le programme comme celui-ci:

sh myprogram.sh ~/documents -l 2 

Je me attends:

Level exist!

Et mais retourne:

Level doesn't exist!

La chose est, si je lance le programme sans le paramètre de position (~/documents) comme ceci:

sh myprogram.sh -l 2

-je obtenir la sortie correcte:

Level exist!

Pourquoi est-ce ? Comment puis-je utiliser les deux paramètres positionnels et getopts dans bash?

Merci!

+0

Si vous êtes sûr que le premier paramètre de position va être votre répertoire, vous pouvez il suffit d'utiliser 'shift' après l'affectation' directory = $ 1'. Mais, comme indiqué, il est probablement préférable de suivre simplement la pratique établie. –

Répondre

2

La plupart des outils sont écrits sous la forme: tool [options] arg ...

Vous devez faire cela:

# first, parse the options: 
while getopts l: flag; do 
    case "$flag" in 
    l) level=$OPTARG;; 
    \?) exit 42;; 
    esac 
done 

# and shift them away 
shift $((OPTIND - 1)) 

# validation 
if [ -n "$level" ]; then 
    echo "Level exist!" 
else 
    echo "Level doesn't exist!" 
fi 

# THEN, access the positional params 
echo "there are $# positional params remaining" 
for ((i=1; i<=$#; i++)); do 
    printf "%d\t%s\n" $i "${!i}" 
done 

Utilisez le \? pour abandonner le script si l'utilisateur fournit une option inconnue ou ne fournit pas nécessaire l'argument

Et l'invoquer comme:

$ bash test.sh 
Level doesn't exist! 
there are 0 positional params remaining 

$ bash test.sh -l 2 
Level exist! 
there are 0 positional params remaining 

$ bash test.sh -l 2 foo bar 
Level exist! 
there are 2 positional params remaining 
1 foo 
2 bar 

$ bash test.sh -x 
test.sh: illegal option -- x 

$ bash test.sh -l 
test.sh: option requires an argument -- l 

Mais vous ne pouvez pas mettre les options après les arguments: getopts arrête lorsque le premier argument non-option se trouve

$ bash test.sh foo bar -l 2 
Level doesn't exist! 
there are 4 positional params remaining 
1 foo 
2 bar 
3 -l 
4 2 
+0

Nice! Cela a fonctionné, donc il n'y a pas de solution pour mettre les opts après les params? – bntzio

+0

Pas avec 'getopts'. Il y a un appel de programme externe 'getopt' qui peut le faire. C'est un peu difficile de travailler avec. Voici un exemple: https://bazaar.launchpad.net/~ubuntu-branches/ubuntu/vivid/util-linux/vivid/view/head:/misc-utils/getopt-parse.bash –