Comparing variables in shell scripts

user3047191 picture user3047191 · Nov 28, 2013 · Viewed 48.5k times · Source

I have got a project that involves shell scripts and comparing values/variables within them. I have looked here and elsewhere on comparing variables and I have tried all the various examples given but I am running into something that is not as advertised. OS is Solaris10

I have created the following script as a learning experience-

#!/bin/ksh

stest()
{
if $X = $Y
then echo they're the same
else echo they're notthe same
fi
}


X=a
Y=a

stest

echo completed

I keep getting some variation of the following-

using shell sh or ksh-

#./test.sh
./test.sh[2]: a:  not found
completed

using shell bash-

#./test.sh
./test.sh: line 5: a: command not found
completed

I have tried enclosing the if $X = $Y line in brackets and double brackets and I get back

[a:  not found  

or

[[a:  not found

If I change the variables X and Y to the numeral "1" I get the same thing-

./test.sh[2]: 1:  not found

I have tried enclosing things in single quotes, double quotes & backwards quotes.

Any help is appreciated.

Answer

After if, you need a shell command, like anywhere else. $X = $Y is parsed as a shell command, meaning $X is interpreted as a command name (provided that the value of the variable is a single word).

You can use the [ command (also available as test) or the [[ … ]] special syntax to compare two variables. Note that you need spaces on the inside of the brackets: the brackets are a separate token in the shell syntax.

if [ "$X" = "$Y" ]; then …

or

if [[ "$X" = "$Y" ]]; then …

[ … ] works in any shell, [[ … ]] only in ksh, bash and zsh.

Note that you need double quotes around the variables¹. If you leave off the quotes, then the variable is split into multiple words and each word is interpreted as a wildcard pattern. This doesn't happen inside [[ … ]], but the right-hand side of = is interpreted as a wildcard pattern there too. Always put double quotes around variable substitutions (unless you want the value of the variable to be used as a list of filename matching patterns, rather than as a string).

¹ Except on $X the [[ … ]] syntax.