Provide two arguments to one option using getopts

39,619

You cannot pass two arguments with single option using getopts.

I recommend the following alternatives:

  1. Put quotes around multiple arguments

    In this case getopts will treat them as one argument, but you will be able to split it later on. You can even put all arguments in the array at once:

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

    The example of run:

    ./script -r "123 456 789"
    

    And output:

    Run Numbers - argument = 123 456 789 
    Number of arguments: 3
    Arguments are: 123, 456, 789
    
  2. Use comma (or other preferred character) as a delimiter

    ./script -r 123,456,789
    

    and you just replace IFS=" " with IFS=, in the code above. That one has the advantage of allowing empty elements. As pointed out in the comments section this solution is chosen by some common programs e.g. lsblk -o NAME,FSTYPE,SIZE.

  3. Allow multiple -r options

    Multiple -r, but each taking only one argument:

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

    Then arguments would be added to array one by one

    array+=("$OPTARG")
    

    That one has the advantage of not having limitations on what characters the elements may contain. This one is also used by some standard linux tools e.g. awk -v var1=x -v var2=y.

Share:
39,619

Related videos on Youtube

ramkrishna
Author by

ramkrishna

I am a research scholar at University of Delhi, Delhi, INDIA. I am doing research in Experimental High Energy Physics. I am working on two topics. First one is the data analysis. For I am analyzing CMS data at 13TeV for extracting aQGC limit with VBF production of W+W-. Also, if time permits as per my PhD schedule we will try to compute its cross-section. My another task is related to the Gas Electron Multiplier (GEM) detectors. Its a gaseous detector and it is going to support muon system from RUN-III onward in CMS. Here I have responsibility for the test beam data analysis with GEM detectors.

Updated on September 18, 2022

Comments

  • ramkrishna
    ramkrishna over 1 year

    In below code when I give option r then getopts requires one arguments:

    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
    

    But I need to pass two arguments after -r option, instead of one. Is there an easy way to do this?

  • PM 2Ring
    PM 2Ring over 9 years
    The comma delimiter idea is good, as it's used by various standard commands, notably mount.
  • jimmij
    jimmij over 9 years
    Possible, one can still transform this "delimited" form into array with array=(${OPTARG//,/ }). Yet another possibility is to just use multiple times -r arg option each time adding element to an array array+=($OPTARG).
  • PM 2Ring
    PM 2Ring over 9 years
    Even easier: IFS=',' array=($OPTARG)
  • Volker Siegel
    Volker Siegel over 9 years
    Examples: pgrep uses comma: ps -s 123,456 ..., grep uses repeating the option: grep -e pattern1 -e pattern2 ... (-e is optional when only one pattern is used).
  • ctrl-alt-delor
    ctrl-alt-delor over 9 years
    you don't want to make the user do more work e.g. put quotes around the list, just because of a limitation in the language/library you are using. However the use of , seems reasonable, even preferable to the use of a space.