LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (http://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   bash: checking if a variable is a number (need regular expression help) (http://www.linuxquestions.org/questions/linux-newbie-8/bash-checking-if-a-variable-is-a-number-need-regular-expression-help-714903/)

anonguy9 03-27-2009 01:16 PM

bash: checking if a variable is a number (need regular expression help)
 
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.

unSpawn 03-27-2009 02:23 PM

Quote:

Originally Posted by anonguy9 (Post 3489837)
Doesn't bash have a way to easily tell if a string is a valid number?

Something like
Code:

typeset -i chkvar; str="$1"; let "foo=$str" 2>/dev/null
was posted before on LQ.

anonguy9 03-27-2009 04:17 PM

Quote:

Originally Posted by unSpawn (Post 3489899)
typeset -i chkvar; str="$1"; let "foo=$str" 2>/dev/null

Searching for typeset and chkvar, I see this thread.

I haven't worked with typeset before, so I didn't know to search for that one.

Edit:

I tested this out, and it's not bad, but it's no better than the math checking. This method won't understand strings which have a period in them, so very common examples like "1.1" and ".1" won't pass.

The regular expression method is still the best so far.

anonguy9 03-27-2009 04:32 PM

duplicate post removed

synss 03-27-2009 05:58 PM

Quote:

Originally Posted by anonguy9 (Post 3489837)
With grep:

Code:

isnumber() {
  if echo $1 | grep '\($regexp\)' &> /dev/null ; then
    return 0
  else
    return 1
  fi
}


What about grep -q? You could then remove all of your if then else return "thingy". And bash can deal with negative numbers, try for yourself
Code:

bash
echo $((-1-1))

I did not read everything from your post.

chrism01 03-28-2009 12:51 AM

1. here's a regex method in pure bash (min version 3.x I believe)
http://www.tldp.org/LDP/abs/html/bas...#REGEXMATCHREF
2. bash can only do integer arithmetic natively, use other tools eg bc for floating point/'decimal'.
Take this into consideration when trying to decide what constitutes a number ...

anonguy9 03-29-2009 02:37 AM

New hotness
 
posting it on my blog instead


All times are GMT -5. The time now is 05:55 PM.