UPDATE: I designed a bunch of regular expressions which seems to work extraordinarily well. See
post #7
----
First, doesn't bash already include a feature to do this?
I do want to achieve this in pure bash, for portability and learning.
I've spent a few hours working on this. I did some hunting and I built a few working examples. I'll paste them all here for completeness, but I did develop a very nice bash-only solution. But to make things just right, I need some help with the regular expression for it.
I've spent a few hours (just today) doing research and trying examples out. Regular expressions make my soul bleed.
There are many other documents out there, none of which seem to help me in my circumstance with my brain, here are some links I've been using:
-
tldp - The comically-titled "Bash Guide for Beginners"
-
faqs.org
-
xytrax.com
Some testing code:
Code:
test() {
check() {
isnumber "$1"
if [ $? -eq 0 ] &>/dev/null ; then
printf "yes"
else
printf "no"
fi
echo " - $1"
}
echo ""
echo "Not numbers: "
check "a"
check "abcdefghijklmnopqrstuvwxyz"
check "a."
check "-a"
check "+a"
check "a1"
check "a1.0"
check "++1"
check "--1"
check "1--"
check "1++"
check "..1"
check "1.."
check "1..0"
check "1.1.1"
check "-"
check "+"
check "."
check "--"
check "++"
check ".."
echo ""
echo "Numbers: "
check "11"
check "1"
check "1."
check ".1"
check "-1"
check "+1"
check "+.1"
check "-.1"
check "1.1"
check "-1.1"
check "+1.1"
}
My regular expression:
Code:
regexp='^[-|+|0-9|.][.0-9]*$'
With grep:
Code:
isnumber() {
if echo $1 | grep '\($regexp\)' &> /dev/null ; then
return 0
else
return 1
fi
}
With sed:
Code:
isnumber() {
check=`echo $1 | sed "s/\($regexp\)//"`
if [ -z ${check} ] ; then
return 0
else
return 1
fi
}
Checking if math can be done on it:
Code:
isnumber() {
if expr $1 + 1 &> /dev/null ; then
echo "yes"
else
echo "no"
fi
}
Leveraging bash typeset (thanks
unSpawn):
Code:
isnumber() {
typeset -i chkvar
let "foo=$1" 2>/dev/null
}
Bash regular expression (the best method so far):
Code:
isnumber() {
if expr match "$1" "\($regexp\)" &> /dev/null ; then
return 0
else
return 1
fi
}
To test:
- Open a terminal
- Paste in the first block of code with test()
- Paste in the method you want to try
- Paste in your regexp= and type "test"
Or if you want to play around with the regular expression, I do this:
Code:
regexp='^[-|+|0-9|.][.0-9]*$';test
Then I can scroll up in my terminal and check, and then press up and edit my previous command to fiddle and fiddle all I like.
----
Questions:
- Doesn't bash have a way to easily tell if a string is a valid number?
- Can bash do math on numbers with a decimal in them?
- Can bash do math on negative numbers?
- Has someone out there written a decent function which can do this?
- Are there any other fringe test cases I should try? (Also, "+" as an input seems to act strangely.. but I haven't tracked that down)
- Could I have a suggestion on other regular expressions to try, or maybe a bit of a pointer on what I'm doing wrong?
- Is there better online documentation on regular expressions which I should know about?
- Are there any regular expression tools which I should check out? (There was one I used in kate, but I have issues getting kate running again and don't want to troubleshoot right now.)
- Are there any tools which could help me build regular expressions in the manner I'm suggesting? (big list of things to match against, expected failures and successes)
----
As an aside, some thoughts..
The fundamental difficulty I (and probably every regular human) seems to be in the way regex expects to be used.
I simply can't comprehend the language which regular expressions talks in. It's something like:
Match only
- stuff like this
- stuff and like that
What I'm expecting to do with regular expressions is more like:
Match everything like like this kind of stuff
- except this kind of stuff
- except that kind of stuff
That's how humans think. We also start counting with one, but that's another story.