I'm trying to match a string of 5 to 7 numbers in a case statement. Nothing I've tried successfully works. This is one of the things I tried.
^[0-9]*$ )
echo "Got it!"
;;
How do I do this successfully?
The patterns in a bash case statement are file globs, not regular expressions. Your best option may be an if/else chain instead of case:
if [[ "$string" =~ ^[0-9]{5,7}$ ]]; then
echo "Got it!"
fi
However, if you are less picky about the exact length, you can use the extended glob feature to match "1 or more digits":
shopt -s extglob
case "$string" in
(+([0-9])) echo "Got it!";;
esac
$ shopt -s extglob
$ isNum() { case $1 in (+([0-9])) echo 'Got it!' ;; esac; }
$ isNum 123A
$ isNum A123
$ isNum 1234
Got it!
If you want to also check length, that might be done separately:
isNum() {
local len=${#1}
if (( len < 5 || len > 7 )); then return; fi
case $1 in (+([0-9])) echo 'Got it!' ;; esac
}
The trick here is "extglob" (extended glob) syntax, which allows functionality similar to proper regular expressions. +(...) in an extglob means "1 or more of ...".
See the bash-hackers page Patterns and pattern matching for details.
Except in ksh93, globs are not powerful enough to match a specific number of repetitions -- you need to actually write that out yourself. For instance:
# this is very clumsy, but works in all POSIX shells
isNum() {
case $1 in [0-9][0-9][0-9][0-9][0-9]) : "Matched 5" ;;
[0-9][0-9][0-9][0-9][0-9][0-9]) : "Matched 6" ;;
[0-9][0-9][0-9][0-9][0-9][0-9][0-9]) : "Matched 7" ;;
*) return ;;
esac
echo "Got it!" # only reached if the "return" didn't happen
}
Thus, you're probably better off using the bash-only regex syntax described in the answer by Mark Reed -- see also the relevant bash-hackers page.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With