Comment gérer la fin des options - dans Getopts


9

J'utilise getopts pour analyser les arguments dans les scripts bash comme

while getopts ":hd:" opt; do
  case $opt in
    d ) echo "directory = $OPTARG"; mydir="$OPTARG"; shift $((OPTIND-1)); OPTIND=1 ;;
    h ) helptext
      graceful_exit ;;
    * ) usage
      clean_up
      exit 1
  esac
done

exeparams="$*"

exeparamscontiendra toutes les options / arguments non analysés. Étant donné que je veux utiliser exeparams pour conserver les options d'une commande à exécuter dans le script (qui peut chevaucher les propres options des scripts), je veux utiliser - pour mettre fin aux options transmises au script. Si je passe par exemple

myscript -d myscriptparam -- -d internalparam

exeparams tiendra

-- -d internalparam

Je veux maintenant supprimer le début --pour passer ces arguments à la commande interne. Existe-t-il un moyen élégant de le faire ou puis-je obtenir une chaîne qui contient juste le reste sans --getopts?


Mettre shift; OPTIND=1à l'intérieur de la getoptsboucle n'est probablement pas la meilleure façon de le faire. Cela ne fonctionne que dans votre cas car vous n'avez que 2 options et dans toutes les autres, vous venez de quitter le script. Sinon, vous auriez besoin shift; OPTIND=1de chaque option, ce qui signifie du code en double (mauvaise pratique). Faites juste un shift $((OPTIND - 1))immédiatement après la fin de la boucle - c'est la manière la plus conventionnelle et probablement la plus efficace aussi.
— jw013

Réponses:


7

Que diriez-vous:

# ... getopts processing ...

[[ $1 = "--" ]] && shift
exeparams=("$@")

Remarque, vous devez utiliser un tableau pour contenir les paramètres. Cela gérera correctement tous les arguments contenant des espaces. Déréférencer le tableau avec"${exeparams[@]}"


1
Cela suppose qu'il n'y a pas d'arguments entre la fin des options et --, c'est script foo -- bar-à- dire qu'ils passeraient foo -- barau programme externe. Ma réponse ne fait pas cette hypothèse car elle n'était pas explicitement énoncée dans la question.
— jw013

Sauf là où l'OP dit "Je veux maintenant supprimer le premier -"
— glenn jackman

C'était pour l'exemple -- -d internalparams. Dans tous les cas, ma réponse est suffisamment générale pour traiter l'un ou l'autre cas.
— jw013

14

Utilisez le intégré shift. Tout d'abord, faites la normale getoptspour votre script. Une fois cette boucle terminée,

shift "$((OPTIND - 1))"

déplacera toutes les options déjà traitées.

À partir de là, vous devrez terminer le traitement des arguments sans option, le cas échéant, dans la première partie du script (avant le --). Une fois que vous rencontrez le --, déplacez-le jusqu'à ce qu'il ne reste que la dernière partie (la -d internalparampartie qui vient après --). Une façon de le faire (en utilisant la bashsyntaxe):

while [[ $# -gt 0 ]]; do
    # process next argument
    case $1 in
    foo) # process foo
    ;;
    --) shift; break;; # found '--', discard it and exit loop
    *) # handle unrecognized argument
    ;;
    esac
    # not '--', so discard the argument and continue
    shift
done

Enfin, il ne reste que le deuxième ensemble d'options / arguments que vous pouvez transmettre. Ne pas utiliser $*pour passer les autres paramètres à une autre commande. Utilisez à la "$@"place, ce qui préserve la division du mot d'origine.

external_command "$@"

Oui merci! Mais comment trouver exactement --?
— highsciguy
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.