Wie verwende ich Muster in einer case-Anweisung?


80

Die manSeite sagt, dass caseAnweisungen "Dateinamen-Erweiterungsmuster-Matching" verwenden.
Normalerweise möchte ich kurze Namen für einige Parameter haben, also gehe ich:

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

logTimeSpentIn "$TASK"

Ich habe versucht, Muster wie req*oder von me{e,}tdenen ich verstehe, dass sie korrekt erweitert werden, um diesen Werten im Kontext der Dateinamenerweiterung zu entsprechen, aber es funktioniert nicht.

Antworten:


157

Brace Expansion nicht funktioniert, aber *, ?und []tun. Wenn Sie festlegen shopt -s extglob, können Sie auch den erweiterten Mustervergleich verwenden :

  • ?() - Null oder eins Muster
  • *() - null oder mehr Mustervorkommen
  • +() - ein oder mehrere Mustervorkommen
  • @() - ein Auftreten von Muster
  • !() - alles außer dem Muster

Hier ist ein Beispiel:

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

2
Link zur Dokumentation dazu: gnu.org/software/bash/manual/html_node/…
Phyatt

@phyatt: Danke. Ich habe den Link zu meiner Antwort hinzugefügt.
Dennis Williamson

Diese Antwort half mir, weil ich mein Muster in doppelte Anführungszeichen ("a *") eingeschlossen hatte und das nicht funktionierte
wytten

44

Ich glaube nicht, dass Sie Zahnspangen verwenden können.

Laut Bash-Handbuch zum Fall in Conditional Constructs .

Jedes Muster wird einer Tilde-Erweiterung, einer Parameter-Erweiterung, einer Befehlsersetzung und einer arithmetischen Erweiterung unterzogen.

Nichts über die Erweiterung der ZahnspangeLeider .

Sie müssten also so etwas tun:

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

7

if und 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

wo:

  • -qverhindert grep, dass eine Ausgabe erzeugt wird, erzeugt nur den Exit-Status
  • -E aktiviert erweiterte reguläre Ausdrücke

Ich mag das, weil:

Ein Nachteil ist, dass dies wahrscheinlich langsamer ist als beim caseAufrufen eines externen grepProgramms, aber ich neige dazu, die Leistung bei der Verwendung von Bash als letztes zu betrachten.

case ist POSIX 7

Bash scheint standardmäßig POSIX zu folgen, ohne shoptwie von erwähnt https://stackoverflow.com/a/4555979/895245 angegeben

Hier ist das Zitat: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_01 Abschnitt "Case Conditional Construct":

Der Fall des bedingten Konstrukts muss die zusammengesetzte Liste ausführen, die dem ersten von mehreren Mustern entspricht (siehe Mustervergleichsnotation). [...] Mehrere Muster mit derselben zusammengesetzten Liste werden durch das '|' Symbol. [...]

Das Format für das Fallkonstrukt lautet wie folgt:

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

und dann http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13 Abschnitt "2.13. Pattern Matching Notation" nur erwähnt ?, *und [].

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.