Search code examples
arraysbashshellwildcardstring-comparison

Shell, compare two script with wildcard


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:

    1. 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)

    2. 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).