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:
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
[[ $var =~ ^-?[0-9]+$ ]]
^indicates the beginning of the input pattern
-is a literal "-"
?means "0 or 1 of the preceding (
+means "1 or more of the preceding (
$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.
Wow... there are so many good solutions here!! Of all the solutions above, I agree with @nortally that using the
-eq one liner is the coolest.
I am running GNU bash, version
4.1.5 (Debian). I have also checked this on ksh (SunSO 5.10).
Here is my version of checking if
$1 is an integer or not:
if [ "$1" -eq "$1" ] 2>/dev/null then echo "$1 is an integer !!" else echo "ERROR: first parameter must be an integer." echo $USAGE exit 1 fi
This approach also accounts for negative numbers, which some of the other solutions will have a faulty negative result, and it will allow a prefix of "+" (e.g. +30) which obviously is an integer.
$ int_check.sh 123 123 is an integer !! $ int_check.sh 123+ ERROR: first parameter must be an integer. $ int_check.sh -123 -123 is an integer !! $ int_check.sh +30 +30 is an integer !! $ int_check.sh -123c ERROR: first parameter must be an integer. $ int_check.sh 123c ERROR: first parameter must be an integer. $ int_check.sh c123 ERROR: first parameter must be an integer.
The solution provided by Ignacio Vazquez-Abrams was also very neat (if you like regex) after it was explained. However, it does not handle positive numbers with the
+ prefix, but it can easily be fixed as below:
[[ $var =~ ^[-+]?[0-9]+$ ]]