Proporcione dos argumentos para una opción usando getopts

10

En el siguiente código cuando doy la opción, rentonces getoptsrequiere un argumento:

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

Pero necesito pasar dos argumentos después de la -ropción, en lugar de uno. ¿Hay una forma fácil de hacer esto?

ramkrishna
fuente

Respuestas:

20

No puede pasar dos argumentos con una sola opción usando getopts.

Recomiendo las siguientes alternativas:

  1. Pon comillas alrededor de múltiples argumentos

    En este caso, getopts los tratará como un argumento, pero podrá dividirlo más adelante. Incluso puede poner todos los argumentos en la matriz a la vez:

    #!/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"
    

    El ejemplo de ejecución:

    ./script -r "123 456 789"

    Y salida:

    Run Numbers - argument = 123 456 789 
    Number of arguments: 3
    Arguments are: 123, 456, 789
    
  2. Use una coma (u otro carácter preferido) como delimitador

    ./script -r 123,456,789

    y simplemente reemplazas IFS=" "con IFS=,en el código de arriba. Ese tiene la ventaja de permitir elementos vacíos. Como se señaló en la sección de comentarios, esta solución es elegida por algunos programas comunes, por ejemplo lsblk -o NAME,FSTYPE,SIZE.

  3. Permitir múltiples -ropciones

    Múltiple -r, pero cada uno toma solo un argumento:

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

    Entonces los argumentos se agregarían a la matriz uno por uno

    array+=("$OPTARG")

    Ese tiene la ventaja de no tener limitaciones sobre qué caracteres pueden contener los elementos. Este también es utilizado por algunas herramientas estándar de Linux, por ejemplo awk -v var1=x -v var2=y.

jimmij
fuente
3
La idea del delimitador de coma es buena, ya que es utilizada por varios comandos estándar, en particular mount.
PM 2Ring
Posible, todavía se puede transformar esta forma "delimitada" en una matriz con array=(${OPTARG//,/ }). Otra posibilidad es usar la -r argopción de varias veces cada vez que agrega un elemento a una matriz array+=($OPTARG).
jimmij
Aún más fácil:IFS=',' array=($OPTARG)
PM 2Ring
Ejemplos: pgrepusa coma: ps -s 123,456 ...grep usa la opción de repetición: grep -e pattern1 -e pattern2 ...( -ees opcional cuando solo se usa un patrón).
Volker Siegel
2
no desea que el usuario trabaje más, por ejemplo, ponga comillas alrededor de la lista, solo por una limitación en el idioma / biblioteca que está utilizando. Sin embargo, el uso de ,parece razonable, incluso preferible al uso de un espacio.
ctrl-alt-delor