做
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
为什么几乎?
隐式
extglob
:当使用“==”和“!=”运算符时,运算符右侧的字符串被视为模式,并根据模式匹配中描述的规则进行匹配,就像启用了 extglob shell 选项一样。
这意味着与选项一起使用的模式
extglob
未设置[[
在 bash 版本 4.3 之后,case 语句和构造内部的工作方式会有所不同。隐式
|
: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
,例如1234
oraabee
,但不匹配12a
orb23
。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