Ich versuche, eine Variable zu verwenden, die aus verschiedenen Zeichenfolgen besteht, die mit einem |
als case
Anweisungstest getrennt sind. Beispielsweise:
string="\"foo\"|\"bar\""
read choice
case $choice in
$string)
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Ich möchte den ersten Teil der Anweisung eingeben foo
oder bar
ausführen können case
. Aber beide foo
und bar
bring mich zum zweiten:
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Verwenden "$string"
statt $string
macht keinen Unterschied. Weder tut mit string="foo|bar"
.
Ich weiß, dass ich es so machen kann:
case $choice in
"foo"|"bar")
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Ich kann mir verschiedene Problemumgehungen vorstellen, möchte aber wissen, ob es möglich ist, eine Variable als case
Bedingung in bash zu verwenden. Ist es möglich und wenn ja, wie?
bash
shell-script
case
terdon
quelle
quelle
eval
, $ Wahl zu entkommen, die Pars, Stern, Semikolons und Zeilenumbrüche. Hässlich, aber es "funktioniert".read
bisschen hielt mich auf. meiner Meinung nach der Validierung von Benutzereingaben, die sind , was dies zu sein scheint,case
Muster sollte nicht an der Spitze der Auswertungsliste sein, und eher das sollte beschneidet nach unten*
Standardmustern , so dass die einzigen Ergebnisse , die es zu erreichen sind akzeptabel garantiert. Da es sich jedoch um eine Analyse- / Erweiterungsreihenfolge handelt, kann eine zweite Bewertung erforderlich sein.Antworten:
Das Bash-Handbuch besagt:
Nein «Pfadnamenerweiterung»
Also: Ein Muster wird NICHT mit «Pfadnamenerweiterung» erweitert.
Deshalb: Ein Muster darf NICHT "|" enthalten. Innerhalb. Nur: Mit dem "|" können zwei Muster verbunden werden.
Das funktioniert:
Verwendung von «Extended Globbing»
Allerdings
word
wird mit abgestimmtpattern
mit «Pathname Expansion» Regeln.Und «Extended Globbing» hier , hier und hier erlaubt die Verwendung alternierender ("|") Muster.
Das funktioniert auch:
String-Inhalt
Das nächste Testskript zeigt, dass das Muster, das mit allen Zeilen übereinstimmt, die entweder
foo
oderbar
irgendwo enthalten,'*$(foo|bar)*'
oder die beiden Variablen$s1=*foo*
und ist$s2=*bar*
Testskript:
quelle
Sie können die
extglob
Option verwenden:quelle
@(foo|bar)
Besondere im Vergleich zufoo|bar
? Beides sind gültige Muster, die bei der wörtlichen Eingabe gleich funktionieren.|
ist nicht Teil des Musters infoo|bar
, sondern Teil der Syntax dercase
Anweisung, um mehrere Muster in einer Klausel zuzulassen.|
ist jedoch Teil des erweiterten Musters.Sie benötigen zwei Variablen,
case
da die|
Pipe or analysiert wird, bevor die Muster erweitert werden.Shell-Muster in Variablen werden auch in Anführungszeichen oder ohne Anführungszeichen unterschiedlich behandelt:
quelle
Wenn Sie ein Dash-kompatibles Workaround wünschen, können Sie Folgendes schreiben:
Erläuterung: awk wird verwendet, um "string" aufzuteilen und jedes Teil separat zu testen. Wenn "choice" mit dem aktuell getesteten Teil p [i] übereinstimmt, wird der awk-Befehl in Zeile 11 mit "exit" beendet. Für den Test wird der "case" der Shell verwendet (innerhalb eines "system" -Aufrufs). , wie von terdon gefragt. Dadurch bleibt die Möglichkeit erhalten, die beabsichtigte Test- "Zeichenfolge" beispielsweise in "foo * | bar" zu ändern, um sie auch für "foooo" ("Suchmuster") abzugleichen, wie es die "Groß- / Kleinschreibung" der Shell zulässt. Wenn Sie stattdessen reguläre Ausdrücke bevorzugen, können Sie den "system" -Aufruf weglassen und stattdessen awks "~" oder "match" verwenden.
quelle