0

I'm trying to create an exit error to expand on the previous script now. if I type anything but a number now and what I have tried so far is:

sum=0
for num in "$@"
do
echo $num | grep -i [^0-9+-]
if ["$?" = 1] then
echo "Sorry, '$num' is not a number"
fi

sum=$((sum + num))  
done
echo $sum

Example if I type in

add 1 2 3 four five

it would say

four
Sorry, 'four' is not a number   
  • it's not clear at all what do you want to achieve. If a string that is not a number is passed you still count it as a number. Is it correct? Also $? = 1 is wrong. the correct syntax is $? -eq 1 but it's better to use $? -gt 0 it's more robust – m47730 Dec 02 '16 at 14:29
  • @m47730 arguably it's better to use `if` with the command directly rather than using `$?` at all. – Tom Fenech Dec 02 '16 at 14:33
  • @TomFenech i agreed with you. I'm saying that it's better to use "-gt 0" instead "-eq 1" – m47730 Dec 02 '16 at 14:44

2 Answers2

1

The following section of your code:

echo $num | grep -i [^0-9+-]
if ["$?" = 1] then

Should be changed to this:

if grep -q '[^0-9+-]' <<< "$num"; then

Inside a test ([), spaces are important but there's no need to use it here anyway. Using -q means that grep doesn't produce output - the exit status indicates whether a match was found or not, so it can be used directly with if.

As mentioned in the comments, the pattern to match a valid integer could be made more robust. Some good ways to detect an integer are shown in this related question. For example, you could change your grep pattern to something like this:

grep -qE '^[+-]?(0|[1-9][0-9]*)$'

or use native regular expressions, as in the most popular answer to that question:

re='^[+-]?(0|[1-9][0-9]*)$'
if [[ $num =~ $re ]]; then
    sum=$((sum + num))
else
    echo "Sorry, '$num' is not a number"
fi

Even this pattern isn't perfect, as it will fail for numbers starting with leading 0s, among other things.

Community
  • 1
  • 1
Tom Fenech
  • 65,210
  • 10
  • 85
  • 122
0

No need to shell out. You can use extended pattern matching to verify the number format:

#!/bin/bash
shopt -s extglob

sum=0
for num in "$@" ; do
    if [[ $num != @(0|?([-+])[1-9]*([0-9])) ]] ; then
        echo "Sorry, '$num' is not a number"
        exit 1
    fi
    (( sum += num ))
done
echo $sum

Note that 09 is not permitted, as it would be interpreted as octal and fail in addition:

value too great for base (error token is "09")
choroba
  • 200,498
  • 20
  • 180
  • 248