it-swarm.com.de

Wie verwende ich Muster in der case-Anweisung in bash-scripting?

Die man-Seite besagt, dass case-Anweisungen "Dateinamenserweiterungsmusterabgleich" verwenden.
Ich möchte normalerweise 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 Muster wie req* oder me{e,}t ausprobiert, von denen ich weiß, dass sie richtig erweitert werden, um diese Werte im Kontext der Dateinamenerweiterung zu finden, dies funktioniert jedoch nicht.

57
Ramiro Rela

Die Klammererweiterung funktioniert nicht, aber *, ? und [] tun dies. Wenn Sie shopt -s extglob setzen, können Sie auch Erweiterte Mustererkennung verwenden:

  • ?() - null oder ein Vorkommen eines Musters
  • *() - null oder mehr Vorkommen eines Musters
  • +() - ein oder mehrere Vorkommen eines Musters
  • @() - ein Vorkommen eines Musters
  • !() - 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
115

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

Laut Bash-Handbuch über Case in Conditional Constructs .

Jedes pattern wird einer Tilde unterzogen Erweiterung, Parametererweiterung, Befehlssubstitution und Arithmetik Erweiterung.

Nichts über Brace Expansion leider.

Also müsstest du so etwas tun:

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

if und grep -E mehr tragbare Lösung

Für die Portabilität empfehle ich, dass Sie einfach if-Anweisungen und grep -E verwenden, die erweiterte reguläre Ausdrücke unterstützen, z.

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

POSIX 7

Die Bash scheint POSIX standardmäßig ohne shopt zu folgen, wie in https://stackoverflow.com/a/4555979/895245 erwähnt

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

Der Bedingungskonstruktionsfall führt die zusammengesetzte Liste aus, die dem ersten von mehreren Mustern entspricht (siehe Musteranpassungsnotation). Mehrere Muster mit derselben zusammengesetzten Liste werden durch das '|' begrenzt. 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 section "2.13. Pattern Matching Notation" erwähnt nur ?, * und [].