While-read and if-elif

Hi there, new to this forum and I recently encounter this problem:

I tried to use if-elif loop in a while-read loop, something like this:

#!/bin/bash
while read myline1 myline2
do
if [ '$myline1 > '$myline2' ]; then
  echo "Successful!"
elif [ '$myline1 < '$myline2' ]; then
  echo "Failed"
fi
done < $1

Input file looks like this:

200 100
100 200 

But the results that I got was:

Successful!
Successful!

It doesn't seems to read the elif condition. Can anyone help?

Thanks!
Ken

Try with this..

#!/bin/bash
while read myline1 myline2
do
if [ '$myline1' > '$myline2' ]; then
  echo "Successful!"
elif [ '$myline1' < '$myline2' ]; then
  echo "Failed"
fi
done < $1

1) Doublequote your variables inside the tests; single quotes prevent variable expansion (and, btw, one quote is missing).
2) use -lt and -gt for numerical comparison; < and > do a string comparison.

Hi there, thanks for the help but I don't think is the issue with the single quote, I tried adding the single quote but has the same result.

Possible that there is other dependencies related?

To add to RudiC's advice:
1) use [[...]] / ((...)) constructs instead of [...] . That way, there is no need to double-quote the variables.

You're using the wrong quotes and they aren't matched. And the < and > operators don't exist in the test utility; you're performing redirections in the operands given to test. Try:

#!/bin/bash
while read myline1 myline2
do
if [ "$myline1" -gt "$myline2" ]; then
echo "Successful!"
elif [ "$myline1" -lt "$myline2" ]; then
echo "Failed"
fi
done < $1

Hi Rudic,

I am not able to understand how we can use < and > signs for string comparison....????

Thanks guys! It's working well now! Thanks again.

bash man page:

According to the standards, you can't with test... and [ ... ] ,
but in [[ ... ]] , < and > are string comparison operators. The -lt and -gt operators perform numeric comparisons in all three forms of these testing methods.

In bash, the < and > are string comparisons in test ... and [ ... ]. In ksh, the < and > will be treated as redirection operators, not string comparisons. I.e., in ksh:

if [ 100 > 200 ]
then echo gt
else echo not gt
fi

will print gt because 100 is not an empty string and will create a file named 200 because > is a redirection operator. But in bash, this same code will print not gt and will not create a file. Both of these behaviors conform to the standards because the standards don't specify any meaning for < and > in these two cases.

=================
I take part of this back. Despite what the bash man page says, at least on Mac OS X, bash and ksh both treat < and > as redirection operators in test and [.

1 Like

Thanks Don Cragun and Rudic,

I have tried out few things. just see below..

For String Operation -

$ if [[ "b" -gt "a" ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ "b" > "a" ]]; then  echo "gt"; else  echo "not gt"; fi
gt

$ if [[ "a" -gt "b" ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ "a" > "b" ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ a -gt b ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ a > b ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ b -gt a ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ b > a ]]; then  echo "gt"; else  echo "not gt"; fi
gt

For numeric operation -

$ if [[ "1" -gt "2" ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ "1" > "2" ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ "2" -gt "1" ]]; then  echo "gt"; else  echo "not gt"; fi
gt

$ if [[ "2" > "1" ]]; then  echo "gt"; else  echo "not gt"; fi
gt

$ if [[ 1 -gt 2 ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ 1 > 2 ]]; then  echo "gt"; else  echo "not gt"; fi
not gt

$ if [[ 2 -gt 1 ]]; then  echo "gt"; else  echo "not gt"; fi
gt

$ if [[ 2 > 1 ]]; then  echo "gt"; else  echo "not gt"; fi
gt

From this i came to conclusion that -

1) Never use -gt and -lt for string comparison.
2) Use > and < for string comparison and -gt and -lt for numeric comparison..
3) String and numbers are compared in sorted order as
Number - 1 - 9 ( like 9 is greater than 1)
String - A,B,C...Z, a,b,c,....z ( like z is greater than a)

these are my few. you can add if you feel so.....:slight_smile:

@pamu: I think this would be a more evident example:

$ [[ 21 > 3 ]] && echo gt || echo lt
lt
$ [[ 21 -gt 3 ]] && echo gt || echo lt
gt

21 interpreted as a string compares less than 3, while as an integer, it compares greater. This is valid for bash; maybe someone can comment on other shells.

1 Like

That's good one.. it clears useless use of < and > while numeric comparison.. removed from numeric comparison...:slight_smile:

As explained in my previous post < and > signs treats as string so they compare each digit by digit. such as..

$ [[ 211 > 12 ]] && echo gt || echo lt        # Here it compares 2 with 1 so 2 is greater than 1 as per sort pattern so gt.
gt

$ [[ 211 > 32 ]] && echo gt || echo lt         #Here it compares 2 with 3 so 3 is greater than 2 as per sort pattern so lt.
lt

Thanks Rudic...

A mnemonic: For numeric comparison, use alphabetic operators (eq, ne, gt, ge, lt, le). Makes perfect sense! :wink:

Regards,
Alister