Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Bash – compare numbers in variable

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

>Solution :

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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading