细节

细节

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

始终表现得与

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

或者有什么陷阱吗?

答案1

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


细节

在构造内部[ … ]

运算=符(甚至 的非 posix 选项==)测试字符串匹配,而不是模式匹配。

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

当使用 == 和 != 运算符时,运算符右侧的字符串被视为模式并根据规则如下面所描述的在模式匹配下。如果外壳选项 nocasematch已启用,则匹配为不考虑具体情况而执行 字母字符。如果字符串与模式匹配 (==) 或不匹配 (!=),则返回值为 0,否则返回值为 1。模式的任何部分都可以被引用以强制将其作为字符串进行匹配。

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

[ [(] 模式 [ | 模式 ] ... ) 列表中的大小写单词 ;; ] ... esac
... 尝试使用相同的匹配依次将其与每个模式进行匹配规则至于路径名扩展(请参阅下面的路径名扩展)。 …检查的每个模式都使用波形符扩展、参数和变量扩展、算术替换、命令替换和进程替换来扩展。如果外壳选项 nocasematch已启用,则执行匹配不考虑案件字母字符。

Pattern Matching在 bash 手册中, 和的Pathname Expansion含义相同。

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

`[[ … ]]`                                   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

quote removal案例构造中没有明确列出这一点。
其工作原理与此完全匹配(对于[[ … ]]):

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

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

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

为什么几乎?

  1. 隐式extglob

    自从bash 版本 4.3

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

    这意味着与选项一起使用的模式extglob 未设置[[在 bash 版本 4.3 之后,case 语句和构造内部的工作方式会有所不同。

  2. 隐式|

    case 的语法是:

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

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

    像这样:

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

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

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

    #!/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
    

相关内容