How to use patterns in a case statement?

后端 未结 3 1629
天涯浪人
天涯浪人 2020-12-04 09:52

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

相关标签:
3条回答
  • 2020-12-04 09:58

    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:

    • it is POSIX 7
    • it supports extended regular expressions, unlike POSIX case
    • the syntax is less clunky than case statements when there are few cases

    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 [].

    0 讨论(0)
  • 2020-12-04 10:04

    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 讨论(0)
  • 2020-12-04 10:19

    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
    
    0 讨论(0)
提交回复
热议问题