[[ 和 bash 中的大小写等效

PSk*_*cik 13 bash wildcards test

if [[ "$1" = pattern ]]; then
    hook
fi
Run Code Online (Sandbox Code Playgroud)

总是表现得一样

case "$1" in
    pattern) hook;;
esac
Run Code Online (Sandbox Code Playgroud)

或者有什么问题吗?

小智 7

是的,它们(几乎)完全等效。


细节

[ … ]构造内部:

=操作者(或甚至非POSIX选项==)测试字符串匹配,而不是模式匹配。

[[ ]]构造内部(来自 man bash):

当使用 == 和 != 运算符时,运算符右侧的字符串被视为一个模式,并根据下面模式匹配中描述的规则进行匹配。如果启用了 shell选项 nocasematch,则执行匹配时不考虑 字母字符的大小写。如果字符串匹配 (==) 或不匹配 (!=) 模式,则返回值为 0,否则为 1。可以引用模式的任何部分以强制将其作为字符串进行匹配。

case构造内部(来自 man bash,编辑并强调我的):

[[(] 模式 [ | 模式 ] ... ) 列表中的 case 词;; ] ... ESAC
...尝试匹配它反过来每个图案,使用相同的匹配规则作为用于路径扩展(见下文路径名扩展)。... 检查的每个模式都使用波浪号扩展、参数和变量扩展、算术替换、命令替换和进程替换进行扩展。如果启用了 shell选项 nocasematch,则执行匹配时不考虑字母字符的大小写

双方Pattern MatchingPathname Expansion用来表示bash的手册中的一样。

我在手册中看到的唯一区别是:

`[[ … ]]`                                   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
Run Code Online (Sandbox Code Playgroud)

quote removal没有为 case 结构明确列出。
哪个可以完全匹配这个(对于[[ … ]]):

可以引用模式的任何部分以强制将其作为字符串进行匹配。

使用它来测试最后一点(现在变量不是模式):

case "$1" in
  "$pattern") echo case match
esac
Run Code Online (Sandbox Code Playgroud)

为什么差不多?

  1. 隐式extglob

    bash 4.3 版开始

    当使用 '==' 和 '!=' 运算符时,运算符右侧的字符串被视为一个模式,并根据以下模式匹配中描述的规则进行匹配,就像启用了 extglob shell 选项一样

    这意味着与选项extglob unset一起使用的模式[[在 bash 版本 4.3 之后的 case 语句和构造中的工作方式不同。

  2. 隐式|

    case 的语法是:

    case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
    
    Run Code Online (Sandbox Code Playgroud)

    这意味着可能有多个由|(OR)分隔的模式。

    像这样:

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

    它将匹配仅包含数字的字符串或仅匹配 中的字母abcde,例如1234or aabee,但不匹配12aor b23

    [[如果使用正则表达式(查看 var p3),A将等效地工作:

    #!/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
    
    Run Code Online (Sandbox Code Playgroud)