Ich versuche, eine Variable zu verwenden, die aus verschiedenen Zeichenfolgen besteht, die durch einen |
getrennt sind als case
Aussagetest. Zum Beispiel:
string=""foo"|"bar""
read choice
case $choice in
$string)
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Ich möchte foo
eingeben können oder bar
und führe den ersten Teil des case
aus Erklärung. Allerdings sind beide foo
und bar
bringt mich zum zweiten:
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Verwenden von "$string"
statt $string
macht keinen Unterschied. Auch nicht die Verwendung von string="foo|bar"
.
Ich weiß, dass ich es so machen kann:
case $choice in
"foo"|"bar")
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Mir fallen verschiedene Problemumgehungen ein, aber ich würde gerne wissen, ob es möglich ist, eine Variable als case
zu verwenden Zustand in bash. Ist das möglich und wenn ja, wie?
Akzeptierte Antwort:
Im Bash-Handbuch heißt es:
case Wort in [ [(] Muster [ | Muster ] … ) Liste;; ] … esac
Jedes untersuchte Muster wird durch Tilde-Erweiterung, Parameter- und Variablen-Erweiterung, arithmetische Substitution, Befehls-Substitution und Prozess-Substitution erweitert.
Keine «Pfadnamenerweiterung»
Also:ein Muster wird NICHT mit «Pathname expansion» erweitert.
Daher:ein Muster darf NICHT „|“ enthalten Innerhalb. Nur:zwei Muster konnten mit dem „|“ verbunden werden.
Das funktioniert:
s1="foo"; s2="bar" # or even s1="*foo*"; s2="*bar*"
read choice
case $choice in
$s1|$s2 ) echo "Two val choice $choice"; ;; # not "$s1"|"$s2"
* ) echo "A Bad choice! $choice"; ;;
esac
Verwendung von „Extended Globbing“
Allerdings word
wird mit pattern
abgeglichen unter Verwendung von „Pathname Expansion“-Regeln.
Und „Extended Globbing“ erlaubt hier, hier und hier die Verwendung von alternierenden („|“) Mustern.
Das funktioniert auch:
shopt -s extglob
string='@(foo|bar)'
read choice
case $choice in
$string ) printf 'String choice %-20s' "$choice"; ;;&
$s1|$s2 ) printf 'Two val choice %-20s' "$choice"; ;;
*) printf 'A Bad choice! %-20s' "$choice"; ;;
esac
echo
String-Inhalt
Das nächste Testskript zeigt, dass das Muster mit allen Zeilen übereinstimmt, die entweder foo
enthalten oder bar
irgendwo ist '*$(foo|bar)*'
oder die beiden Variablen $s1=*foo*
und $s2=*bar*
Testskript:
shopt -s extglob # comment out this line to test unset extglob.
shopt -p extglob
s1="*foo*"; s2="*bar*"
string="*foo*"
string="*foo*|*bar*"
string='@(*foo*|*bar)'
string='*@(foo|bar)*'
printf "%sn" "$string"
while IFS= read -r choice; do
case $choice in
"$s1"|"$s2" ) printf 'A first choice %-20s' "$choice"; ;;&
$string ) printf 'String choice %-20s' "$choice"; ;;&
$s1|$s2 ) printf 'Two val choice %-20s' "$choice"; ;;
*) printf 'A Bad choice! %-20s' "$choice"; ;;
esac
echo
done <<-_several_strings_
f
b
foo
bar
*foo*
*foo*|*bar*
"foo"
"foo"
afooline
onebarvalue
now foo with spaces
_several_strings_