Free tech support / small logo


Test for valid numbers in a Bash shell script?

In a different discussion on this site [see Redirecting input in a shell script] a visitor commented that "I was too busy trying to make sure the above post made sense that I forgot to ask for help. If you can, please post examples of how I can make the second argument a requirement and evaluate if it is a number. Thank you in advance!"


Dave's Answer:

There are simple solutions to both issues, and I really dig into these in my popular book Wicked Cool Shell Scripts (pay special attention to script #5, validating numeric input), so I'm going to crib a bit from that script to show you how I solved this...

First off, it's pretty easy to require a positional parameter be specified, either by checking the number of arguments given (with $#) or by simply testing the specific positional parameter for a non-null value (e.g. $2).

Really, all you do is test if it's specified, then have whatever code subsequent that you want. In this case, I strongly suggest a "usage" message along with whatever error you'd like. In fact, my scripts almost always have a usage message with details about parameters and expected input formats if you skip any input at all.

Back to the test, though! The first test would look like this:

if [ $# -ne 2 ] ; then...

and the second test, if you prefer just looking at the individual parameter, would look like this:

if [ -z "$2" ] ; then

(check the man page for 'test' if you want to know what the -z flag does, but if you're writing shell scripts, it should already be something you're familiar with. :-)

The bigger question is how you validate for numbers only, and my general approach for testing argument value is to basically push the input through a 'strainer' and see what comes out the other end.

In this case, I'm going to use "sed" to replace all digits with null and see if the remainder is itself null (meaning that the argument was just digits) or not.

First step, to filter out the digits:

nodigits="$(echo $testvalue | sed 's/[[:digit:]]//g')"

Now to test the result:

if [ ! -z $nodigits ] ; then
  echo "Invalid number format! Only digits, no commas, spaces, etc." >&2
  exit 1
fi

If you want to allow negative integers, it gets a tiny bit more complicated, but you just have to test the very first character to see if it's a minus sign, and if so, remove it. I'd suggest using "cut -c1" to get the first character, and "cut -c2-" for everything after that first digit. Something like this:

if [ "$(echo $2 | cut -c1)" = "-" ] ; then ...

Of course, in the book I have a much fancier solution that I prefer, but it's hard to remember when you're whipping out a script to accomplish a specific task:

if [ "${number%${number#?}}" = "-" ] ; then # first char '-' ?

In any case, I hope that helps clarify how to both force a parameter and then test it to see if it's a valid number or not. Oh, and in the book I have a really complicated script function that tests for valid real / floating point numbers. Considerably more complex...


Also check out:








Subscribe!
Never miss another Q&A article! Click to subscribe: Add to Google Reader Add to My Yahoo! Subscribe in NewsGator RDF XML
Comments · Add Comment
Starbucks coffee cup I do have a lot to say, and questions of my own for that matter, but first I'd like to say thank you for all your efforts on this Web site by buying you a cup of coffee!
Rather amazingly, there are no comments on this article yet.

I do have a comment, now that you mention it!











Remember personal info?


Please note that I will never send you any unsolicited email. Ever.

While I'm at it, please note that by submitting a question or comment you're agreeing to my terms of service, which are: you relinquish any subsequent rights of ownership to your material by submitting it on this site.









Recent Entries


Search
I Need Help!
Need Help? Ask Dave Taylor!


© 2002 - 2012 by Dave Taylor. All Rights Reserved.

Note: This web site is for the purpose of disseminating information for educational purposes, free of charge, for the benefit of all visitors. We take great care to provide quality information. However, we do not guarantee, and accept no legal liability whatsoever arising from or connected to, the accuracy, reliability, currency or completeness of any material contained on this web site or on any linked site.

[whiteboard marker tray]
"Ask Dave Taylor®" is a registered trademark of Intuitive Systems, LLC.