13

Does

if [[ "$1" = pattern ]]; then
    hook
fi

always behave the same as

case "$1" in
    pattern) hook;;
esac

or are there any gotchas?

  • 1
    I can't find any cases where they differ, regardless of shopt settings and values in $1 or pattern, nor in $? afterwards. The only difference is that $1 is not expanded in the output when running under xtrace. – Kusalananda Jul 8 '16 at 11:05
7

Yes, they are (almost) completelly equivalent.


Detail

Inside a [ … ] construct:

The = operator (or even the non-posix option of == ) tests string matching, not pattern matching.

Inside a [[ ]] construct (from man bash):

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.

Inside a case construct (from man bash, edited and emphasis mine):

case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
... tries to match it against each pattern in turn, using the same matching rules as for pathname expansion (see Pathname Expansion below). … Each pattern examined is expanded using tilde expansion, parameter and variable expansion, arithmetic substitution, command substitution, and process substitution. If the shell option nocasematch is enabled, the match is performed without regard to the case of alphabetic characters.

Both Pattern Matching and Pathname Expansion are used to mean the same inside the bash manual.

The only difference I can see in the manual is:

`[[ … ]]`                                   case
tilde  expansion                            tilde expansion
parameter and variable expansion            parameter and variable expansion
arithmetic expansion                        arithmetic substitution
command substitution                        command substitution
process substitution                        process substitution
quote removal

That quote removal is not explicitly listed for the case construct.
Which works to exactly match this (for the [[ … ]]):

Any part of the pattern may be quoted to force it to be matched as a string.

Use this to test this last point (now the variable is not a pattern):

case "$1" in
  "$pattern") echo case match
esac

Why almost?

  1. Implicit extglob:

    Since version 4.3 of bash

    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 in Pattern Matching, as if the extglob shell option were enabled.

    That means that a pattern used with the option extglob unset will work differently in a case statement and inside a [[ construct after bash version 4.3.

  2. Implicit |:

    The syntax for case is:

    case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
    

    Which means that there may be several patterns separated by a | (OR).

    Like this:

    shopt -s extglob;      p1="+([0-9])";       p2="+([abcde])"
    
    case "$1" in
        $p1|$p2)    echo "or case match" ; ;;
    esac
    

    Which will match either a string of only numbers or only letters in abcde, like 1234 or aabee, but not 12a or b23.

    A [[ will work equivalently if regex (look at var p3) are used:

    #!/bin/bash
    
    shopt -s extglob           ### Use extended globbing.
    shopt -s globasciiranges   ### The range [a-z] will expand to [abcdefghijklmnopqrstuvwxyz].
    
    pattern="+([0-9])"
    p1="+([0-9])"
    p2="+([a-z])"
    p3="^([0-9]+|[a-z]+)$"
    
    case "$1" in
        $pattern)   echo case1 match ; ;&
        $p1|$p2)    echo case2 match ; ;;
    esac
    
    [[ "$1" == $pattern ]] && echo if1 match
    [[ "$1" =~ $p3 ]] && echo if2 match
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.