Gibt es in Bash/Bourne einen „In“-Operator?

Gibt es in Bash/Bourne einen „In“-Operator?

Ich suche nach einem „In“-Operator, der ungefähr so ​​funktioniert:

if [ "$1" in ("cat","dog","mouse") ]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Es handelt sich dabei offensichtlich um eine viel kürzere Anweisung als beispielsweise bei der Verwendung mehrerer „oder“-Tests.

Antwort1

Sie können verwenden case...esac

$ cat in.sh 
#!/bin/bash

case "$1" in 
  "cat"|"dog"|"mouse")
    echo "dollar 1 is either a cat or a dog or a mouse"
  ;;
  *)
    echo "none of the above"
  ;;
esac

Ex.

$ ./in.sh dog
dollar 1 is either a cat or a dog or a mouse
$ ./in.sh hamster
none of the above

Mit ksh, bash -O extgloboder zsh -o kshglobkönnen Sie auch ein erweitertes Glob-Muster verwenden:

if [[ "$1" = @(cat|dog|mouse) ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

Mit bash, ksh93oder zshkönnen Sie auch einen Vergleich mit regulären Ausdrücken verwenden:

if [[ "$1" =~ ^(cat|dog|mouse)$ ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

Antwort2

In Bash gibt es keinen „In“-Test, aber einen Regex-Test (nicht in Bourne):

if [[ $1 =~ ^(cat|dog|mouse)$ ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Und normalerweise mithilfe einer Variablen geschrieben (weniger Probleme mit Anführungszeichen):

regex='^(cat|dog|mouse)$'

if [[ $1 =~ $regex ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Für eine ältere Bourne-Shell müssen Sie die Groß-/Kleinschreibung beachten:

case $1 in
    cat|dog|mouse)   echo "dollar 1 is either a cat or a dog or a mouse";;
esac

Antwort3

Die Verwendung von a caseist in Ordnung, wenn Sie einen festen Satz von Haustieren haben, mit denen Sie vergleichen möchten. Es funktioniert jedoch nicht, wenn Sie das Muster zur Laufzeit erstellen müssen, da casees die Abwechslung innerhalb erweiterter Parameter nicht interpretiert.

Dies entspricht nur der wörtlichen Zeichenfolge cat|dog|mouse:

patt='cat|dog|mouse'
case $1 in 
        $patt) echo "$1 matches the case" ;; 
esac

Sie können jedoch eine Variable mit der regulären Ausdrucksübereinstimmung verwenden. Solange die Variable nicht in Anführungszeichen steht, haben alle darin enthaltenen Regex-Operatoren ihre spezielle Bedeutung.

patt='cat|dog|mouse'
if [[ "$1" =~ ^($patt)$ ]]; then
        echo "$1 matches the pattern"
fi

Sie können auch assoziative Arrays verwenden. Die Überprüfung, ob ein Schlüssel in einem Array vorhanden ist, kommt einem inOperator, den Bash bietet, am nächsten. Allerdings ist die Syntax ein wenig hässlich:

declare -A arr
arr[cat]=1
arr[dog]=1
arr[mouse]=1

if [ "${arr[$1]+x}" ]; then
        echo "$1 is in the array"
fi

(${arr[$1]+x}wird erweitert auf , xwenn arr[$1]gesetzt ist, andernfalls leer.)

Antwort4

grepAnsatz.

if echo $1 | grep -qE "^(cat|dog|mouse)$"; then 
    echo "dollar 1 is either a cat or a dog or a mouse"
fi
  • -qum jegliche Ausgabe auf dem Bildschirm zu vermeiden (schneller einzutippen als >/dev/null).
  • -Efür erweiterte reguläre Ausdrucksaspekte (cat|dog|mouse)ist dies erforderlich.
  • ^(cat|dog|mouse)$^passt zu allen Zeilen, die mit Katze, Hund oder Maus ( ) beginnen, (cat|dog|mouse)gefolgt vom Zeilenende ( $)

verwandte Informationen