Test whether string is a valid integer

Richard T picture Richard T · Feb 5, 2010 · Viewed 159.1k times · Source

I'm trying to do something common enough: Parse user input in a shell script. If the user provided a valid integer, the script does one thing, and if not valid, it does something else. Trouble is, I haven't found an easy (and reasonably elegant) way of doing this - I don't want to have to pick it apart char by char.

I know this must be easy but I don't know how. I could do it in a dozen languages, but not BASH!

In my research I found this:

Regular expression to test whether a string consists of a valid real number in base 10

And there's an answer therein that talks about regex, but so far as I know, that's a function available in C (among others). Still, it had what looked like a great answer so I tried it with grep, but grep didn't know what to do with it. I tried -P which on my box means to treat it as a PERL regexp - nada. Dash E (-E) didn't work either. And neither did -F.

Just to be clear, I'm trying something like this, looking for any output - from there, I'll hack up the script to take advantage of whatever I get. (IOW, I was expecting that a non-conforming input returns nothing while a valid line gets repeated.)

snafu=$(echo "$2" | grep -E "/^[-+]?(?:\.[0-9]+|(?:0|[1-9][0-9]*)(?:\.[0-9]*)?)$/")
if [ -z "$snafu" ] ;
then
   echo "Not an integer - nothing back from the grep"
else
   echo "Integer."
fi

Would someone please illustrate how this is most easily done?

Frankly, this is a short-coming of TEST, in my opinion. It should have a flag like this

if [ -I "string" ] ;
then
   echo "String is a valid integer."
else
   echo "String is not a valid integer."
fi

Answer

Ignacio Vazquez-Abrams picture Ignacio Vazquez-Abrams · Feb 5, 2010
[[ $var =~ ^-?[0-9]+$ ]]
  • The ^ indicates the beginning of the input pattern
  • The - is a literal "-"
  • The ? means "0 or 1 of the preceding (-)"
  • The + means "1 or more of the preceding ([0-9])"
  • The $ indicates the end of the input pattern

So the regex matches an optional - (for the case of negative numbers), followed by one or more decimal digits.

References: