Comparison treating strings as zero integers

I'm trying to write a bash script to perform basic arithmetic operations but I want to run a comparison on the arguments first to check that they're a number greater than zero.

I want an error to pop up if the arguments args aren't >= 0 so I have:

if ! [[ $1 -ge 0 ]]; then
echo "bad number: $1"
fi

But whenever I type in something like "blah + 9" it should tell me "bad number: blah", instead it treats "blah" as a zero and it gives the output as 9. If I use -gt 0 it eliminates the "blah" but also doesn't let me use zeros.

#! /bin/bash

if [[ `echo $1 | egrep "^[0-9]*$"` ]]
then
    echo "good number: $1"
else
    echo "bad number: $1"
fi
if [[ $1 == ?(+)+([0-9]) ]]
then
echo positive number
else
echo not a positive number
fi

Neither of those cures my problem. It still reads non numbers as zero.

case "$string" in
[0-9]*) ;;
-[0-9]*) ;;
*) echo "Not integer" ;;
esac

Whoa, I have no idea what that means. Can you please explain the logic behind this? I'll try it now though.

could you please post your input and output with the script.

For the first two:
Input:

./math 3 p sd

Output:

Result is 3

With case it gives:

./math: Bad left number "3"
./math: Bad right number "sd"
Result is 3

Isn't this working?

Perhaps it will work with these small adjustments:

#! /bin/sh
if [ -n "$(echo "$1" | egrep "^[0-9]+$")" ]; then
  echo "good number: $1"
else
  echo "bad number: $1"
fi

Be sure to copy it exactly.
egrep "^[0-9]+$" is only allowing integers - no spaces and no ",", ".", "+" or "-", you have to adjust that if you want to allow more.

Check this...

$ sh test.sh 5
good number: 5     #$1 is 5

$ sh test.sh fg
bad number: fg   #$1 is fg

$ sh test.sh 3 gfg 5
good number: 3    #$1 is 3

$ sh test.sh "3 gfg 5"
bad number: 3 gfg 5     #$1 is "3 gfg 5"

$ cat test.sh
#! /bin/bash

if [[ `echo $1 | egrep "^[0-9]*$"` ]]
then
    echo "good number: $1"
else
    echo "bad number: $1"
fi

Try this :

#!/bin/bash

a='blah'
[ "$a" -eq 0 ] 2>/dev/null ; x="$?"     # Get error status to x variable
# As per man bash, if x greater than 1, $a is not an integer
if [ "$x" -gt 1 ]; then
        echo 'Bad integer'
fi

exit 0

This worked (though I'm sure egrep would've been fine too):

if ! [[ `echo $1 | grep "^[0-9]*$"` ]]

Also, decided to put a counter in each of the improper argument tests so that I could stop the script only after each test finished. Is there a more efficient way of doing this?

let probs=0

#each test if then 
let probs++

#after all tests finish
if [[ probs -ne 0 ]]
then
exit
fi

eeek! and a new question... how do I make it so my script doesn't try to use any of bash's special characters in the arguments?

blah:~$ ./math *& p 2
[1] 9028
-bash: p: command not found
blah:~$ usage: ./math <number> <operation> <number>
./math 3 p 2
Result is 5
[1]+  Done                    ./math *

ctrl+c kills the goofy stuff after it but I don't want to do that whenever some weird crap pops up, want it totally idiot proof.

What you describe is a feature of the shell, giving 'idiots' access to a shell is the problem here. Perhaps you should consider some sort of menu-driven utility rather than shell access.

Oh well. And I'm the idiot here, learning to program :stuck_out_tongue:

Thanks for the help everyone!

Yes, but it's better when things can be done with built-in functions.
You may not remark any speed in your example, but it can save you some time when you use these external programs within loops.

Like this?

#!/bin/bash

testInt() {
	[ "$1" -eq 0 ] 2>/dev/null
	[ "$?" -gt 1 ] && { testResult=$((testResult+1)); return 1;}
	return 0
}

a='blah'
testInt "$a" && {
	echo "Do whatever you want with $a, but you won't see this first message, because $a is not an integer"
}

b='1234'
testInt "$b" && {
	echo "Do whatever you want with $b, you see this message, because $b is an integer"
}

[ "$testResult" -gt 0 ] && {
	echo "$testResult test(s) failed. Exiting the script now"
	exit 1
}

echo 'None of the tests failed, we continue up to the next exit 0'

exit 0