The Bash FAQ says
If you're validating a simple "string of digits", you can do it with a glob:
# Bash
if [[ $foo = *[!0-9]* ]]; then
echo "'$foo' has a non-digit somewhere in it"
else
echo "'$foo' is strictly numeric"
fi
I thought, "Goody, that looks nice and simple".
I then pasted exactly that into a script, except I added "exit 1" after the first echo and changed $foo
to $1
, so that it looked like
if [[ $1 = *[!0-9]* ]]; then
echo "'$1' has a non-digit somewhere in it"
exit 1
else
echo "'$1' is strictly numeric"
fi
I then tried to run this and got
$ sh foo.sh bar
bar
foo.sh: 6: [[: not found
'bar' is strictly numeric
I'm Bash illiterate, I'm ashamed to say, so I've no idea what could be wrong here. I had the impression, supported by the online Bash manual that the operator for matching with regexes is =~
, but changing that doesn't make any difference. And that [[
operator that seems to be problematic here looks standard, though I don't know what the difference is between [[ ]]
and [ ]
, which both correspond to testing the expression, as far as I know. I'm using Debian squeeze with bash
$ bash --version
GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu)
Debian says version 4.1-3
.
Best Answer
Why are you calling
sh
, if that's a bash script? It's clear that on your system,sh
is not bash, but some other shell in the Bourne/POSIX family. In fact, it's dash, a smaller shell designed for low memory consumption and speed that pretty much only supports POSIX constructs and built-in utilities.[[ … ]]
is a ksh extension to the Bourne syntax that was picked up by bash and zsh but not by POSIX. In a portable script, you need to use[ … ]
for tests. The standard construct doesn't have any support for pattern matching; the standard idiom is to use acase
construct:Here's a function that tests if its argument is all-digits:
Digression: I initially made a typo in the snippet above: I'd written
$(($0-1))
. This caused odd-looking error messages:$0
is the name of the script, so the arithmetic expression to be evaluated wasfoo.sh-1
or./foo.sh-1
. You can watch the diversity of error mesages amongst shells. I was a little surprised to see that ash's messages and bash's message without./
were the clearest: none of the other shells mention that the problem is in an arithmetic expression. Ash and pdksh do get docked points for reporting the error one line too far.