Forneça dois argumentos para uma opção usando getopts

10

No código abaixo, quando eu dou a opção r, getoptsrequer um 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

Mas preciso passar dois argumentos após a -ropção, em vez de um. Existe uma maneira fácil de fazer isso?

ramkrishna
fonte

Respostas:

20

Você não pode passar dois argumentos com uma única opção usando getopts.

Eu recomendo as seguintes alternativas:

  1. Coloque aspas em vários argumentos

    Nesse caso, o getopts os tratará como um argumento, mas você poderá dividi-lo mais tarde. Você pode até colocar todos os argumentos na matriz de uma 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"

    O exemplo de execução:

    ./script -r "123 456 789"

    E saída:

    Run Numbers - argument = 123 456 789 
    Number of arguments: 3
    Arguments are: 123, 456, 789
  2. Use vírgula (ou outro caractere preferido) como um delimitador

    ./script -r 123,456,789

    e você apenas substitui IFS=" "por IFS=,no código acima. Esse tem a vantagem de permitir elementos vazios. Como apontado na seção de comentários, esta solução é escolhida por alguns programas comuns, por exemplo lsblk -o NAME,FSTYPE,SIZE.

  3. Permitir várias -ropções

    Múltiplos -r, mas cada um tendo apenas um argumento:

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

    Em seguida, os argumentos seriam adicionados à matriz, um por um

    array+=("$OPTARG")

    Esse tem a vantagem de não ter limitações sobre quais caracteres os elementos podem conter. Este também é usado por algumas ferramentas padrão do Linux, por exemplo awk -v var1=x -v var2=y.

jimmij
fonte
3
A ideia do delimitador de vírgula é boa, pois é usada por vários comandos padrão, principalmente mount.
PM 2Ring
Possível, ainda é possível transformar esse formulário "delimitado" em matriz com array=(${OPTARG//,/ }). Ainda outra possibilidade é usar a -r argopção de várias vezes a cada vez que adicionar elemento a uma matriz array+=($OPTARG).
jimmij
Ainda mais fácil:IFS=',' array=($OPTARG)
PM 2Ring
Exemplos: pgrepusa vírgula ps -s 123,456 ...:, grep usa a opção: grep -e pattern1 -e pattern2 ...( -eé opcional quando apenas um padrão é usado).
Volker Siegel
2
você não quer que o usuário trabalhe mais, por exemplo, coloque aspas na lista, apenas por causa de uma limitação no idioma / biblioteca que você está usando. No entanto, o uso de ,parece razoável, até preferível ao uso de um espaço.
Ctrl-alt-delor 26/10/14