Fournissez deux arguments à une option à l'aide de getopts

10

Dans le code ci-dessous lorsque je donne une option, ril getoptsfaut alors un argument:

while getopts ":hr::l:" opt; do
    case $opt in
        r ) echo "Run Numbers - argument = $OPTARG " ;;
        l ) echo "Latency range - argument = $OPTARG" ;;
        h ) helptext
            graceful_exit ;;
        * ) usage
            clean_up
            exit 1
    esac
done

Mais je dois passer deux arguments après l' -roption, au lieu d'un. Y a-t-il un moyen facile de faire ceci?

ramkrishna
la source

Réponses:

20

Vous ne pouvez pas passer deux arguments avec une seule option à l'aide de getopts.

Je recommande les alternatives suivantes:

  1. Mettez des guillemets autour de plusieurs arguments

    Dans ce cas, getopts les traitera comme un seul argument, mais vous pourrez le diviser plus tard. Vous pouvez même mettre tous les arguments dans le tableau à la fois:

    #!/bin/bash  
    
    while getopts ":hr:l:" opt; do
        case $opt in
            r ) echo "Run Numbers - argument = $OPTARG "
                set -f # disable glob
                IFS=' ' # split on space characters
                array=($OPTARG) ;; # use the split+glob operator
            l ) echo "Latency range - argument = $OPTARG" ;;
            h ) helptext
                graceful_exit ;;
            * ) usage
                clean_up
                exit 1
        esac
    done
    
    echo "Number of arguments: ${#array[@]}"
    echo -n "Arguments are:"
    for i in "${array[@]}"; do
      echo -n " ${i},"
    done
    printf "\b \n"

    L'exemple de course:

    ./script -r "123 456 789"

    Et sortie:

    Run Numbers - argument = 123 456 789 
    Number of arguments: 3
    Arguments are: 123, 456, 789
  2. Utilisez une virgule (ou un autre caractère préféré) comme délimiteur

    ./script -r 123,456,789

    et vous remplacez simplement IFS=" "par IFS=,dans le code ci-dessus. Celui-ci a l'avantage de permettre des éléments vides. Comme indiqué dans la section des commentaires, cette solution est choisie par certains programmes courants, par exemple lsblk -o NAME,FSTYPE,SIZE.

  3. Autoriser plusieurs -roptions

    Multiple -r, mais prenant chacun un seul argument:

    ./script -r 123 -r 456 -r 789

    Ensuite, les arguments seraient ajoutés au tableau un par un

    array+=("$OPTARG")

    Celui-ci a l'avantage de ne pas avoir de limitations sur les caractères que les éléments peuvent contenir. Celui-ci est également utilisé par certains outils Linux standard, par exemple awk -v var1=x -v var2=y.

jimmij
la source
3
L'idée du délimiteur de virgule est bonne, car elle est utilisée par diverses commandes standard, notamment mount.
PM 2Ring
Possible, on peut encore transformer cette forme "délimitée" en tableau avec array=(${OPTARG//,/ }). Encore une autre possibilité consiste à simplement utiliser l' -r argoption plusieurs fois à chaque fois en ajoutant un élément à un tableau array+=($OPTARG).
jimmij
Encore plus facile:IFS=',' array=($OPTARG)
PM 2Ring
Exemples: pgreputilise la virgule ps -s 123,456 ...:, grep utilise la répétition de l'option: grep -e pattern1 -e pattern2 ...( -eest facultative lorsqu'un seul modèle est utilisé).
Volker Siegel
2
vous ne voulez pas que l'utilisateur fasse plus de travail, par exemple, mettez des guillemets autour de la liste, juste à cause d'une limitation dans la langue / bibliothèque que vous utilisez. Cependant l'utilisation de ,semble raisonnable, voire préférable à l'utilisation d'un espace.
ctrl-alt-delor