I am trying to compare two "almost" identical strings in a shell script.
They are similar except for one character (A-Z).
In the example below I want the code to return true for all cases of the string from
1-2-3-A-5-6-
to 1-2-3-Z-5-6-
Currently my code returns false.
#!/bin/bash
TEMPLATE='1-2-3-*-5-6-'
CASE='1-2-3-A-5-6-'
if [[ "$TEMPLATE" == "$CASE" ]]; then
echo "It's there."
else
echo "NO, improve!"
fi
>Solution :
The pattern 1-2-3-*-5-6-
is a glob.
This pattern language is described in the Pattern Matching section of the bash manual, and available to both the [[ == ]]
test you’re trying to use (manual quoted below), and the case
version mentioned in a comment.
[[ expression ]]
… 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, as if the extglob shell option were enabled. The=
operator is equivalent to
==
. If the nocase‐
match shell option is enabled, the match is performed without regard to the case of alphabetic characters.
… Any part of the pattern may be quoted to force the
quoted portion to be matched as a string.
There are only two constraints:
-
you can’t quote the pattern if you want it to be matched as a pattern rather than a literal string
(see the last quoted paragraph)
-
the pattern must go on the right hand side of the operator
(first paragraph)
So your code will work fine as
#!/bin/bash
TEMPLATE='1-2-3-*-5-6-'
CASE='1-2-3-A-5-6-'
if [[ $CASE == $TEMPLATE ]]; then
echo "It's there."
else
echo "NO, improve!"
fi
NB. Part of the reason for using the built-in [[ ]]
conditions instead of the old [ ]
ones is specifically that
Word splitting and pathname expansion are not performed on the words between the
[[
and]];
so you don’t generally need to quote variables (and in this particular case, must not quote at least one of them).