Free tech support / small logo


String comparisons don't work in shell scripts?

I'm a bit baffled. I'm trying to compare string variables in a shell script to figure out if one value is lexically less (that is, would appear earlier in the dictionary) than another, but it doesn't seem to work at all? Help!


Dave's Answer:

I'm pretty sure you're asking about the conditional string expressions in the test command, typically denoted in shell scripts with the [ and ] symbols (the first of which, as a complete piece of trivia, is actually a hard link to the test binary. Do the following to see it: ls /usr/bin/? or /bin/? instead!)

Anyway, you're trying to do something like this:

if [ $stringvar1 > $stringvar2 ] ; then
  echo $stringvar1 is greater than $stringvar2
else
  echo $stringvar1 is not greater than $stringvar2
fi

The problem with this notation, one that surprisingly few shell script books and articles mention, is that you need to escape the angle brackets or the shell will interpret them as redirection symbols!

Indeed, if you have stringvar1=test and stringvar2=me then running that test would actually create an output file called "me", not at all what you want to accomplish!

Instead, here's a snippet of code to experiment with that demonstrates the correct use of these string conditionals:

#!/bin/sh

a="aardvark" # then try 'zebra'
b="banjo"

if [ $a \< $b ] ; then
  echo "$a is less than $b"
else
  echo "$a is NOT less than $b"
fi

exit 0

Hope that helps clear up the mystery!









Subscribe!
Never miss another Q&A article! Click to subscribe: Add to Google Reader Add to My Yahoo! Subscribe in NewsGator RDF XML
Comments

Thanks for the Hint , For whomever you wrote it it helped my purpose

Posted by: Athreya at July 30, 2007 6:12 AM

In string comparisons in shell scripts, instead of using "test expression" or "[ expression ]," I suggest that folks try using the "extended test facility" (not available in all shells). The extended test facility is "[[ expression ]]," like so:

[[ $str1 < $str2 ]]

Notice that I purposely left out the backslash character before the angle bracket above. It seems to work fine on my system (OSX Snow Leopard ver. 10.6.8). The extended test facility is supposed to require less quoting (because it doesn't do word splitting or pathname expansion), and indeed, that seems to be the case here.

Notice that I've included spaces liberally around everything above. It's been my experience in working with language translators (interpreters [like the shell command interpreters] and compilers) that this helps with debugging, because it often seems to make it easier for the translator to give more meaningful error messages when it encounters a syntax error. If you compress and run things together as much as possible, with as little white space as possible, then it makes things worse--not only for the error processing routines to try and guess at what you meant, but also for humans trying to read the code!

So, I try to space things apart whenever possible; removing extra spaces only when absolutely necessary. It seems like, in some programming environments, programmers have traditionally done just the opposite. Of course, there are some situations where spaces must not be used; the trick seems to be in knowing when they're required, when they're optional, and when they must be left out.

If you happen to know for sure that spaces won't work in a particular place, then don't put them in. Otherwise, if you're not sure whether spaces will work or not, I suggest that you either put them in (and test your code accordingly) or else read enough of the documentation to determine whether to include them or leave them out in that particular place.

Note that using the extended test facility probably will make a shell script less portable. So, if portability is important to you, you probably should either do some testing on the different systems and shells you plan to use, or else stick to the other, more universal, ways of doing this, such as the "test expression" and "[ expression ]" facilities that are in most shells.

The new code then becomes:

#!/bin/sh

a="aardvark" # then try 'zebra'
b="banjo"

if [[ $a < $b ]] ; then
echo "$a is less than $b"
else
echo "$a is NOT less than $b"
fi

exit 0

The above code produced the correct output for me, both for "aardvark" and for "zebra".

Posted by: Bruce Brown at January 23, 2012 7:03 PM

I have something to say, now that you mention it, but ...
Starbucks coffee cup I do have a lot to say, and questions of my own for that matter, but first I'd like to say thank you for all your efforts on this Web site by buying you a cup of coffee!

I do have a comment, now that you mention it!











Remember personal info?


Please note that I will never send you any unsolicited email. Ever.

While I'm at it, please note that by submitting a question or comment you're agreeing to my terms of service, which are: you relinquish any subsequent rights of ownership to your material by submitting it on this site.









Recent Entries


Search
I Need Help!
Need Help? Ask Dave Taylor!


© 2002 - 2012 by Dave Taylor. All Rights Reserved.

Note: This web site is for the purpose of disseminating information for educational purposes, free of charge, for the benefit of all visitors. We take great care to provide quality information. However, we do not guarantee, and accept no legal liability whatsoever arising from or connected to, the accuracy, reliability, currency or completeness of any material contained on this web site or on any linked site.

[whiteboard marker tray]
"Ask Dave Taylor®" is a registered trademark of Intuitive Systems, LLC.