bash getopts, intervalli di analisi


0

Quale sarebbe l'approccio migliore per analizzare gli intervalli di valori degli argomenti utilizzando getopts ? Come esempio:

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

Nel mio script avrei quindi una matrice con i valori 2, 3, 4, 6, 8, 9 e 10.


1
Non ho esperienza con getopts, ma se utilizzi Bash, perché non espandi l'intervallo prima, ad es. {2..4}?
slhck

Non ci ho mai pensato, funziona molto bene. Un problema è che devo usare più opzioni: -r {2..4} -r6 -r {8..10}.
c0dem4gnetic

@Bhargav Bhat Hai legato al torto getopt(3), che non è lo stesso di getopt(1).
slhck

@slhck: oops! è corretto ora.
Bhargav Bhat

Risposte:


1

Se vuoi usare entrambi -r ..., .. e -r ... -r ... -r ...: crea uno script come questo "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[@]}"

e poi eseguirlo:

$ ./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

Volevo dare solo suggerimenti, ma ho scoperto che scrivere è meglio. Questo rende una risposta lunga, ma spero che aiuti!


Brillante! Grazie per aver aggiunto commenti nello script per renderlo più facile da seguire!
c0dem4gnetic

prego. Alcune parti potrebbero aver bisogno di commenti, quindi se avete domande sul modo in cui ho scritto questo o quello, per favore chiedete.
Olivier Dulac

Ho corretto "elif" in modo che corrisponda a quello che ci aspettiamo (altrimenti potrebbe contenere caratteri indesiderati aggiuntivi prima e dopo)
Olivier Dulac
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.