4

I'm writing a script that executes scripts stored in a given directory, based on an array containing the filenames of the scripts. Here's a section of my 'menu', just to clarify:

#######

Title: Test script 1
Description: Test script 1
To execute: 0

#######

Title: Test script 2
Description: Test script 2
To execute: 1

#######

I have an array named array that contains the names of the scripts with an index corresponding to the printed value under "to execute". Right now, I'm using a case statement to handle input and provide an exit option.

case $REPLY in 
     [Ee]) clear
           exit;;
     [[:digit:]] $scriptDirectory/${array[$REPLY]}

However, the [[:digit:]] expression only matches 0-9. I need a regex that works in the case statement that matches 0-999, or similar.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Thorne Garvin
  • 410
  • 1
  • 5
  • 12

4 Answers4

5

case only uses globs (aka filename expansion patterns), not regular expressions.

You can set extended glob with shopt -s extglob, then you can use +() to match one or more occurrence :

shopt -s extglob

case $REPLY in 
     [Ee]) clear
           exit;;
     +([[:digit:]])) $scriptDirectory/${array[$REPLY]};;
esac

Note : I added missing ) after your second case pattern and missing ;; at the end of the same line. Also added the esac missing statement.

Update :

If you just want to match numbers between 0 and 999, try this :

     [0-9]?([0-9])?([0-9]))  $scriptDirectory/${array[$REPLY]};;

Character range are used here as I find it a bit more readable. The result will be the same.

SLePort
  • 15,211
  • 3
  • 34
  • 44
2

The easiest way I've found is bash is:

^(1000|[0-9]{1,3})$

Using this regex combined with the =~ operator (which interprets the string to the right as an extended regular expression) you can construct a simple test. (with your input as "$1")

if [[ $1 =~ ^(1000|[0-9]{1,3})$ ]]; then
    echo "0 <= $1 <= 1000 (1)"
else
    echo "$1 - invalid number"
fi

Example Use/Output

$ for i in -10 -1 0 1 10 100 999 1000 1001; do ./zero1thousand.sh $i; done
-10 - invalid number
-1 - invalid number
0 <= 0 <= 1000
0 <= 1 <= 1000
0 <= 10 <= 1000
0 <= 100 <= 1000
0 <= 999 <= 1000
0 <= 1000 <= 1000
1001 - invalid number
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

In this simple case I suggest you use something like below :

REPLY="$1" # I assumed there is an argument to the script

if [[ $1 =~ ^[[:digit:]]+$ ]]
then
   padded_REPLY=$(printf "%04d" "$REPLY")
   #echo "Padded reply : $padded_REPLY"
else
   padded_REPLY="$REPLY"
   echo "Padded reply : $padded_REPLY"
fi

regexp1="^[[:digit:]]{4}$" #checks padded_REPLY is in the range 0000 to 1000 
#the input is padded 
regexp2="[eE]+$"

if [[ "$padded_REPLY" =~ $regexp1 ]]
then
   if [ "$REPLY" -le 1000 ] #checking script exist
   then
     echo "$REPLY" # I just echoed, you do the stuff below
     #"$scriptDirectory/${array[$REPLY]}"
   else
     echo "Scripts are numbered from 0 to 1000"
   fi       
elif [[ "$padded_REPLY" =~ $regexp2 ]]
then
  clear
  exit
fi

But getopts is suggested to for smarter argument management.

sjsam
  • 21,411
  • 5
  • 55
  • 102
0

Give a try to this:

case $REPLY in
  [Ee]) 
        clear
        exit 0;;

  [[:digit:]]|[[:digit:]][[:digit:]]|[[:digit:]][[:digit:]][[:digit:]]|1000) 
        $scriptDirectory/${array[$REPLY]}
        exit 0;;
esac

The involved pattern list matches 1 digit or 2 digits or 3 digits or 1000.

The pattern used with case is described in Pattern Matching Notation from the Open Group.

Please note that this is not a regular expression.

There is at least one thing taken from Regular Expression; this is the [] (RE Bracket Expression). It is used to match a single char. So, [[:digit:]] is valid. It matches a single char which could be any digit.

To match several digits, it is needed to concatenate several patterns matching a single character, e.g. use [[:digit:]][[:digit:]] to match 2 digits.

| can be used to match more than one pattern. To match a number between 0 and 99, i.e. one digit or 2 digits numbers, use [[:digit:]]|[[:digit:]][[:digit:]]

Jay jargot
  • 2,745
  • 1
  • 11
  • 14