Thursday, February 21, 2008

Compare strings and numbers in shell

Comparison operators and syntaxes of comparisons are different for different languages. For example 'eq' keyword in perl used in comparisons of strings, and in shell '-eq' used for comparisons of numbers.

The more interesting thing, that even for bash ( most often used as interactive shell) and ksh (used for scripts), results of comparisons would be different for absolutly the same expression.

Example is:


$ ksh
$ set -o vi #for more convinient command-line editing
$ if [ "b " -eq " b" ] ; then echo "hurray" ; else echo "dfdfd" ; fi
hurray
$ bash
rtg@kubic-roman:~$ if [ "b " -eq " b" ] ; then echo "hurray" ;
else echo "dfdfd" ; fi
bash: [: b numerical expression expected
dfdfd


Incorrect comparison used; compared strings as numbers. Got two different tests results for .ksh and bash, and bash reported problem, but .ksh not.

Now fix expression, and use "=" operator as specified.

~$ ksh
$ set -o vi
$ if [ "b " = " b" ] ; then echo "equal" ; else echo "non equal" ; fi
non equal
$ bash
rtg@kubic-roman:~$ if [ "b " = " b" ] ; then echo "equal" ; else echo "non equal" ; fi
non equal


It is correct, and same for both expressions.

What will be, if numerical comparison used for string containing numbers?
It is more simple to display it in script:

$ ksh
$ if [ "7" -eq ' 7 ' ] ; then echo "equal" ; else echo "non equal" ; fi
equal
$ if [ "7" == ' 7 ' ] ; then echo "equal" ; else echo "non equal" ; fi
non equal

the same results are in the bash.

Consclusion:


If move from another language, especially statically typed like C:

- be patient with scripts (especially comparisons)

- if a script does not report any error, it still can be buggy; C program probably won't even compile for cases processed by shell script with hidden error.

- If some command in script failed, and even produced error message, script continues execution if else not specified in the script. Some of the errors of this type could be avoided by always checking result of command execution after each command in script.

- Test cases are needed, especially when migrate/upgrade to new toolset/system, even if application code is unchanged.

Why this post have been written:


Switching from one programming language to the another is popular.
It is because modern systems are heterogeneous.

The problem: often the same entity in contest of one programming language, present something complete different in contest of another language.

It is simple to use only one language. You can be sure in such a case, that when you are coding automatically, you are using exact syntax from the language used, but not from some another language.

It is complex, when use a lot of languages.

When switching from one language to another, looking through short reference card of language you switched from, and that of language you switched in, can be useful. It can help to place yourself in right contest, and get rid of previous contest.

Perl and Shell scripts, that are often similar in construction, have different variable declaration, but the same definition (shell does not use $ when defining variable), tests are different, function definitions i.t.c.

No comments: