How to use patterns in a case statement?

The man page says that case statements use "filename expansion pattern matching".
I usually want to have short names for some parameters, so I go:

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

I tried patterns like req* or me{e,}t which I understand would expand correctly to match those values in the context of filename expansion, but it doesn't work.

3 Answers

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 
4

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 
0

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

Here is the quote: 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 section "2.13. Pattern Matching Notation" only mentions ?, * and [].

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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

You Might Also Like