Home > Enterprise >  Bash - compare numbers in variable
Bash - compare numbers in variable

Time:09-27

I'm trying to find errors in log, and I need to send message if any number of error is greater than 0.

My script looks like this:

var1=$(grep Errors: rclone.log | awk '{print $2;}')
for i in "${var1}"
do
if [ "$i" -gt "0" ]; then
echo "Errors"
else
echo "No errors"
fi
done

Variable $i looks like this

0 2 1 0 0 0 10  

But if I run my script, I'm always see errors like this:

./test.sh: line 7: [: 0
2
1
0
0
0
10: integer expression expected

So my idea, is to find all number in $i greater than 0. Where is my mistake?

My input file:

Checking:
Errors:                 0
Checks:            741286 / 751291, 99%
Transferred:         2005 / 2005, 100%
Elapsed time:    39m26.2s
Checking:
Errors:                 0
Checks:            741465 / 751470, 99%
Transferred:         2005 / 2005, 100%
Elapsed time:    39m26.7s
Checking:
Errors:                 10
Checks:            741616 / 751621, 99%
Transferred:         2005 / 2005, 100%
Elapsed time:    39m27.2s

CodePudding user response:

The double quotes around ${var1} cause the for loop to only loop once, using the entire value of the variable as the sole value of $i. So you end up comparing the string 0 (newline) 2 (newline) 1 etc against the number 0, which is not well-defined. See also When to wrap quotes around a shell variable?

The indirection via a variable seems superfluous, too. A minimal fix would look like

awk '/Errors:/ {print $2;}' rclone.log |
while read -r i
do
    if [ "$i" -gt 0 ]; then
        echo "Errors"
    else
        echo "No errors"
    fi
done

This fixes the useless grep but keeps the bug that it will print "No errors" every time there is a zero in the input, and "Errors" for every other result. I'm guessing you simply wanted to print something once, and that should be "Errors" if there was at least one non-zero result?

Anyway, if you are already using Awk, you are better off writing all of this in Awk.

awk '/Errors:/ { if($2>0)   e }
  END { print (e ? "Errors" : "No errors")
    exit e>1 }' rclone.log

Notice also how this sets the exit code from Awk to produce a machine-readable result you can use directly in a script ... maybe something like

if awk ...>/dev/null; then
    echo "$0: do panic!" >&2
fi
  • Related