s="STP=20"
if [[ "$x" == *"$s"* ]]
The if
condition is always false; why?
s="STP=20"
if [[ "$x" == *"$s"* ]]
The if
condition is always false; why?
Try this: http://tldp.org/LDP/abs/html/comparison-ops.html
string comparison
=
is equal to
if [ "$a" = "$b" ]
There is a difference in testing for equality between [ ... ]
and [[ ... ]]
.
The [ ... ]
is an alias to the test
command:
STRING1 = STRING2 the strings are equal
However, when using [[ ... ]]
When the
==
and!=
operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below under Pattern Matching. If the shell option nocasematch is enabled, the match is performed without regard to the case of alphabetic characters. The return value is 0 if the string matches (==
) or does not match (!=
) the pattern, and 1 otherwise. Any part of the pattern may be quoted to force it to be matched as a string.
The same seems to be true with just the =
sign:
$ foo=bar
$ if [[ $foo = *ar ]]
> then
> echo "These patterns match"
> else
> echo "These two strings aren't equal"
> fi
These patterns match
Note the difference:
$ foo=bar
> if [ $foo = *ar ]
> then
> echo "These patterns match"
> else
> echo "These two strings aren't equal"
> fi
These two strings aren't equal
However, there are a few traps with the [ $f00 = *ar ]
syntax. This is the same as:
test $foo = *ar
Which means the shell will interpolate glob expressions and variables before executing the statement. If $foo
is empty, the command will become equivalent to:
test = *ar # or [ = *ar ]
Since the =
isn't a valid comparison operator in test
, you'll get an error like:
bash: [: =: unary operator expected
Which means the [
was expecting a parameter found in the test
manpage.
And, if I happen to have a file bar
in my directory, the shell will replace *ar
with all files that match that pattern (in this case bar
), so the command will become:
[ $foo = bar ]
which IS true.
To get around the various issues with [ ... ]
, you should always put quotes around the parameters. This will prevent the shell from interpolating globs and will help with variables that have no values:
[ "$foo" = "*ar" ]
This will test whether the variable $foo
is equal to the string *ar
. It will work even if $foo
is empty because the quotation marks will force an empty string comparison. The quotes around *ar
will prevent the shell from interpolating the glob. This is a true equality.
Of course, it just so happens that if you use quotation marks when using [[ ... ]]
, you'll force a string match too:
foo=bar
if [[ $foo == "*ar" ]]
then
echo "This is a pattern match"
else
echo "These strings don't match"
fi
So, in the end, if you want to test for string equality, you can use either [ ... ]
or [[ ... ]]
, but you must quote your parameters. If you want to do glob pattern matching, you must leave off the quotes, and use [[ ... ]]
.
To compare two strings in variables x
and y
for equality, use
if test "$x" = "$y"; then
printf '%s\n' "equal"
else
printf '%s\n' "not equal"
fi
To test whether x
appears somewhere in y
, use
case $y in
(*"$x"*)
printf '%s\n' "$y contains $x"
;;
(*)
printf '%s\n' "$y does not contain $x"
;;
esac
Note that these constructs are portable to any POSIX shell, not just bash. The [[ ]]
construct for tests is not (yet) a standard shell feature.
I do not know where you came up with the *
, but you were real close:
s="STP=20"
if [[ "STP=20" == "$s" ]]; then
echo "It worked!"
fi
You need to escape =
using \
in the string s="STP=20"
s="STP\=20"
if [[ "STP\=20" == "$s" ]]; then echo Hi; else echo Bye; fi