web-dev-qa-db-fra.com

Utilisation de getopts dans une fonction Bash

Je voudrais utiliser getopts dans une fonction que j'ai définie dans mon .bash_profile. L'idée est que j'aimerais passer quelques drapeaux à cette fonction pour modifier son comportement.

Voici le code:

function t() {
    echo $*
    getopts "a:" OPTION
    echo $OPTION
    echo $OPTARG
}

Quand je l'invoque comme ceci:

t -a bc

J'obtiens cette sortie:

-a bc
?
 

Qu'est-ce qui ne va pas? Je voudrais obtenir la valeur bc sans décaler ni analyser manuellement. Comment utiliser correctement getopts dans une fonction?

EDIT: corrigé mon extrait de code pour essayer $ OPTARG, en vain

EDIT # 2: OK s'avère que le code est bien, mon Shell a été en quelque sorte foiré. L'ouverture d'une nouvelle fenêtre l'a résolu. La valeur arg était en effet dans $ OPTARG.

41
Magnus

Comme le souligne @Ansgar, l'argument de votre option est stocké dans ${OPTARG}, mais ce n'est pas la seule chose à surveiller lors de l'utilisation de getopts dans une fonction. Vous devez également vous assurer que ${OPTIND} est local à la fonction en la désactivant ou en la déclarant local, sinon vous rencontrerez un comportement inattendu lorsque vous invoquerez la fonction plusieurs fois.

t.sh:

#!/bin/bash

foo()
{
    foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; }

    local OPTIND o a
    while getopts ":a:" o; do
        case "${o}" in
            a)
                a="${OPTARG}"
                ;;
            *)
                foo_usage
                ;;
        esac
    done
    shift $((OPTIND-1))

    echo "a: [${a}], non-option arguments: $*"
}

foo
foo -a bc bar quux
foo -x

Exemple d'exécution:

$ ./t.sh
a: [], non-option arguments:
a: [bc], non-option arguments: bar quux
foo: [-a <arg>]

Si vous commentez # local OPTIND, voici ce que vous obtenez à la place:

$ ./t.sh
a: [], non-option arguments:
a: [bc], non-option arguments: bar quux
a: [bc], non-option arguments:

En dehors de cela, son utilisation est la même que lorsqu'elle est utilisée en dehors d'une fonction.

86

Voici un exemple simple d'utilisation de getopts dans la fonction Shell:

#!/usr/bin/env bash
t() {
  local OPTIND
  getopts "a:" OPTION
  echo Input: $*, OPTION: $OPTION, OPTARG: $OPTARG
}
t "$@"
t -a foo

Production:

$ ./test.sh -a bc
Input: -a bc, OPTION: a, OPTARG: bc
Input: -a foo, OPTION: a, OPTARG: foo

Comme @ a souligné Adrian , local OPTIND (ou OPTIND=1) doit être défini car Shell ne réinitialise pas OPTIND automatiquement entre plusieurs appels à getopts (man bash).

La syntaxe de base pour getopts est:

getopts OPTSTRING VARNAME [ARGS...]

et par défaut, ne pas spécifier d'arguments équivaut à l'appeler explicitement avec "$ @" qui est: getopts "a:" opts "$@".

En cas de problème, voici les variables utilisées par getopts pour vérifier:

  • OPTIND - l'index de l'argument suivant à traiter,
  • OPTARG - la variable est définie sur n'importe quel argument pour une option trouvée par getopts,
  • OPTERR (pas POSIX) - défini sur 0 ou 1 pour indiquer si Bash doit afficher les messages d'erreur générés par getopts.

De plus, voir: Petit tutoriel getopts sur le wiki Bash Hackers

10
kenorb

L'argument est stocké dans la variable $OPTARG.

function t() {
  echo $*
  getopts "a:" OPTION
  echo $OPTION
  echo $OPTARG
}

Production:

$ t -a bc
-a bc
a
bc
5
Ansgar Wiechers