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.