Serge
Serge

Reputation: 741

What bash compare operator always works for string and numeric comparisons

Migrated to Almalinux 9 from CentOS 7 I've written a simplest Bash script to control quantity of inotifywait processes (must be 11) - but I was very surprised the results depending on compare operator used.

(BASH - GNU bash, version 5.1.8(1)-release (x86_64-redhat-linux-gnu))

#!/bin/bash
itf=$(ps aux | grep [i]notify | wc -l); 
status=$(mysql -uroot -N -e 'SELECT status FROM db.table WHERE filename LIKE "rates.xml"');
echo "$itf";  # correct value - 11
echo "$status";  # correct value - OK
printf "First compare numeric\n"
if [[ "itf" -eq 11 ]] ; then 
echo "OK - all 11 inotifywait processes run";
else
printf  "Just $itf inotifywait processes running of 11\n";
fi
printf "Second compare string just experiment\n"
if [[ "$status" != "OK" ]]; then
echo STATUS BAD ;
else
echo STATUS GOOD ;
fi
exit ;
    sh

I do not see any errors in coding above - but result for count is wrong. In spite of bash counted 11 processes (as should be) - it shows negative result

Just 11 inotifywait processes running of 11

But when I change compare operator from

if [[ "itf" = 11 ]] ; then 

to

if [[ "itf" -eq 11 ]] ; then 

then I have positive result as should be

OK - all 11 inotifywait processes run

At the same time it seems NO MATTER what operator to use when compare strings. I was tested both

if [[ "$status" != "OK" ]]; then
if [[ "$status" -ne "OK" ]]; then

both cases we have correct result

STATUS GOOD

No matter run script as SH or BASH.

My question is - should we ALWAYS use in bashes the "text" compare operators like "-ne", "-eq" etc - because they are UNIVERSAL for all kind of comparisons, string or numeric or whatever else ? Thx in advance for your opinions,

Upvotes: -1

Views: 52

Answers (1)

KamilCuk
KamilCuk

Reputation: 141533

In Bash there are only strings.

-ne -eq compare numbers, or in the context of [[, arithmetic expressions.

In arithmetic expression, string that is not a variable is replaced by 0.

$ if [[ "OK" -eq 0 ]]; then echo true; fi
true
$ if [[ "literally_anything" -eq 0 ]]; then echo true; fi
true
$ if [[ "literally_anything" -eq "something_completely_else" ]]; then echo true; fi
true
$ literally_anything=1
$ something_completely_else=2
$ if [[ "literally_anything" -eq "something_completely_else" ]]; then echo true; else echo false; fi
false
 if [[ "itf" -eq 11 ]] ; then 

itf is a variable. -eq evaluates itf and expands it.

You meant to write if [[ "$itf" = 11 ]] ; then to compare strings in your code.

It might be more readable to if ((itf == 11)).

 if [[ "$status" -ne "OK" ]]; then

$status expands to some text. This text happens not to be a variable. So it becomes 0. OK is also not a variable, so it becomes 0.

What bash compare operator always works for string and numeric comparisons

None. = compares strings. -ne -eq compare numbers.

Upvotes: 2

Related Questions