Предоставить два аргумента одной опции, используя getopts

10

В ниже код , когда я даю вариант , rто getoptsтребуется один аргументы:

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

Но мне нужно передать два аргумента после -rопции, а не один. Есть простой способ сделать это?

Ramkrishna
источник

Ответы:

20

Вы не можете передать два аргумента с использованием одной опции getopts.

Я рекомендую следующие альтернативы:

  1. Кавычки вокруг нескольких аргументов

    В этом случае getopts будет рассматривать их как один аргумент, но вы сможете разбить его позже. Вы можете даже поместить все аргументы в массив сразу:

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

    Пример запуска:

    ./script -r "123 456 789"

    И вывод:

    Run Numbers - argument = 123 456 789 
    Number of arguments: 3
    Arguments are: 123, 456, 789
    
  2. Используйте запятую (или другой предпочтительный символ) в качестве разделителя

    ./script -r 123,456,789

    и вы просто заменить IFS=" "с IFS=,в коде выше. У этого есть преимущество, позволяющее пустые элементы. Как указано в разделе комментариев, это решение выбирают некоторые распространенные программы, например lsblk -o NAME,FSTYPE,SIZE.

  3. Разрешить несколько -rвариантов

    Несколько -r, но каждый принимает только один аргумент:

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

    Затем аргументы будут добавлены в массив один за другим

    array+=("$OPTARG")

    Преимущество этого состоит в отсутствии ограничений на символы, которые могут содержать элементы. Этот также используется некоторыми стандартными инструментами Linux, например awk -v var1=x -v var2=y.

jimmij
источник
3
Идея разделителя запятых хороша, так как она используется различными стандартными командами, в частности mount.
PM 2Ring
Возможно, все еще можно преобразовать эту «разделенную» форму в массив с array=(${OPTARG//,/ }). Еще одна возможность - просто использовать -r argопцию многократно каждый раз, добавляя элемент в массив array+=($OPTARG).
Джимми
Еще проще:IFS=',' array=($OPTARG)
PM 2Ring
Примеры: pgrepиспользует запятую:, ps -s 123,456 ...grep использует повторение опции: grep -e pattern1 -e pattern2 ...( -eнеобязательно, когда используется только один шаблон).
Фолькер Сигел
2
Вы не хотите, чтобы пользователь выполнял больше работы, например, помещал в список кавычки, просто из-за ограничения в используемом языке / библиотеке. Однако использование ,кажется разумным, даже предпочтительнее использования пространства.
Ctrl-Alt-Delor