如何在案例陈述中使用模式?

man页面显示,case语句使用“文件名扩展模式匹配”。
我通常需要一些参数的简称,所以我这样做:

case $1 in
req|reqs|requirements) TASK="Functional Requirements";;
met|meet|meetings) TASK="Meetings with the client";;
esac


logTimeSpentIn "$TASK"

我尝试了像 req*me{e,}t这样的模式,我知道它们可以正确地展开,以便在文件名展开的上下文中匹配这些值,但它们不起作用。

131038 次浏览

I don't think you can use braces.

According to the Bash manual about case in Conditional Constructs.

Each pattern undergoes tilde expansion, parameter expansion, command substitution, and arithmetic expansion.

Nothing about Brace Expansion unfortunately.

So you'd have to do something like this:

case $1 in
req*)
...
;;
met*|meet*)
...
;;
*)
# You should have a default one too.
esac

Brace expansion doesn't work, but *, ? and [] do. If you set shopt -s extglob then you can also use extended pattern matching:

  • ?() - zero or one occurrences of pattern
  • *() - zero or more occurrences of pattern
  • +() - one or more occurrences of pattern
  • @() - one occurrence of pattern
  • !() - anything except the pattern

Here's an example:

shopt -s extglob
for arg in apple be cd meet o mississippi
do
# call functions based on arguments
case "$arg" in
a*             ) foo;;    # matches anything starting with "a"
b?             ) bar;;    # matches any two-character string starting with "b"
c[de]          ) baz;;    # matches "cd" or "ce"
me?(e)t        ) qux;;    # matches "met" or "meet"
@(a|e|i|o|u)   ) fuzz;;   # matches one vowel
m+(iss)?(ippi) ) fizz;;   # matches "miss" or "mississippi" or others
*              ) bazinga;; # catchall, matches anything not matched above
esac
done

if and grep -Eq

arg='abc'
if echo "$arg" | grep -Eq 'a.c|d.*'; then
echo 'first'
elif echo "$arg" | grep -Eq 'a{2,3}'; then
echo 'second'
fi

where:

  • -q prevents grep from producing output, it just produces the exit status
  • -E enables extended regular expressions

I like this because:

One downside is that this is likely slower than case since it calls an external grep program, but I tend to consider performance last when using Bash.

case is POSIX 7

Bash appears to follow POSIX by default without shopt as mentioned by https://stackoverflow.com/a/4555979/895245

Here is the quote: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_01 section "Case Conditional Construct":

The conditional construct case shall execute the compound-list corresponding to the first one of several patterns (see Pattern Matching Notation) [...] Multiple patterns with the same compound-list shall be delimited by the '|' symbol. [...]

The format for the case construct is as follows:

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

and then http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13 section "2.13. Pattern Matching Notation" only mentions ?, * and [].