Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

What would the best approach be to parse argument value ranges using getopts? As an example:

$ script.sh -r2-4,6,8-10

In my script I would then have an array with the values 2, 3, 4, 6, 8, 9 and 10.

share|improve this question
1  
I have no experience with getopts, but if you're using Bash, why not expand the range before, e.g. {2..4}? –  slhck Dec 27 '12 at 10:17
    
Never thought of that, it works very well. One issue is that I have to use multiple options: -r{2..4} -r6 -r{8..10}. –  c0dem4gnetic Dec 27 '12 at 10:26
    
@Bhargav Bhat You linked to the wrong getopt(3), which is not the same as getopt(1). –  slhck Dec 27 '12 at 10:41
    
@slhck: oops! is corrected now. –  Bhargav Bhat Dec 27 '12 at 10:43
add comment

1 Answer

up vote 1 down vote accepted

If you want to both use -r...,.. and -r... -r... -r... : create a script such as this "toto.bash" :

#!/usr/bin/bash

    add_ranges () #this will add each integers or ranges (a-b) into the array: myarray
    {
       #first we test that we only have those validchars (makes the second step below much easier to write)
       validchars='[1234567890,-]'
       echo "$@" | grep "${validchars}" >/dev/null && {
          : ; #only valid chars, probably ok. (but could be wrong, ex: 1-  2,, 4-3  etc...)
       } || {
          echo "The ranges you entered are not valid : they should only contain such characters: ${validchars}"
          exit 1 ;
       }
       #secondly we now try to handle the current ranges lists (comma separated)
       for range in $(echo "${@}" | tr ',' ' ')
       do
          if   [[ ${range} =~ ^[0-9]+$ ]]     # [[ can handle regexp matching, and doesn't need to quote parameters
          then
             myarray[${#myarray[*]}]=${range}  #add this after the latest element in myarray
          elif [[ ${range} =~ ^[0-9]+-[0-9]+$ ]]
          then
             newrange=$(echo "$range" | sed -e 's/-/../')
             for i in `eval echo {$newrange}` # {a..b} means: all integers a to b
             do
                myarray[${#myarray[*]}]=${i}  #add this after the latest element in myarray
             done
          else
             echo "ERROR: I can not recognize this range: $range"
             exit 1
          fi
       done
    }

   ###### handle options using getopts:
   OPTIND=1; #here for compatibility's sake: in case you add another function that uses getopts, reminds you to re-set OPTIND each time.
   while getopts "r:" zeoption; do
      case $zeoption in
         r)
        allranges="${OPTARG}";
            add_ranges "${OPTARG}";
            ;;
         -)
        echo "option --, OPTARG=$OPTARG";
            break ;
            ;;
         *)
        echo "ERROR: Unrecognized option: zeoption=$zeoption OPTARG=$OPTARG";
            shift
            ;;
      esac;
   done;

   shift $((OPTIND-1)) ; #we shift away all the options we processed.
   ###### end of options handling

    # and we continue here...

   echo "we now have : remaining arguments: ${@}"
   echo "and myarray contains: ${myarray[@]}"

and then run it:

$ ./toto.bash -r 2,4,6-12 -r 100-103 foo bar
we now have : remaining arguments: foo bar
and myarray contains: 2 4 6 7 8 9 10 11 12 100 101 102 103

I wanted to give just hints, but foudn out that writing it out is better. This makes for a long answer, but I hope it helps!

share|improve this answer
    
Brilliant! Thank you for adding comments in the script to make it easier to follow! –  c0dem4gnetic Dec 27 '12 at 13:20
    
you're welcome. Some parts may need comments, so if you have questions about the way I wrote this or that, please do ask. –  Olivier Dulac Dec 27 '12 at 13:28
    
I corrected the "elif" so that it closely match what we expect (otherwise it could contain additionnal unwanted characters before and after) –  Olivier Dulac Dec 27 '12 at 13:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.