J'essaie d'utiliser une variable composée de différentes chaînes séparées par un |
comme un case
essai de déclaration. Par exemple :
string=""foo"|"bar""
read choice
case $choice in
$string)
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Je veux pouvoir taper foo
ou bar
et exécutez la première partie du case
déclaration. Cependant, les deux foo
et bar
emmenez-moi à la seconde :
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Utilisation de "$string"
au lieu de $string
ça ne fait aucune différence. Utiliser string="foo|bar"
non plus .
Je sais que je peux le faire de cette façon :
case $choice in
"foo"|"bar")
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Je peux penser à différentes solutions de contournement, mais j'aimerais savoir s'il est possible d'utiliser une variable comme case
condition en bash. Est-ce possible et si oui, comment ?
Réponse acceptée :
Le manuel bash indique :
mot cas dans [ [(] motif [ | motif ] … ) liste;; ] … esac
Chaque modèle examiné est développé à l'aide d'un développement de tilde, d'un développement de paramètres et de variables, d'une substitution arithmétique, d'une substitution de commande et d'une substitution de processus.
Pas de "développement du nom de chemin"
Ainsi :un motif n'est PAS développé avec «Développement du chemin».
Par conséquent :un modèle ne peut PAS contenir "|" à l'intérieur. Uniquement :deux modèles peuvent être joints avec le "|".
Cela fonctionne :
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
Utilisation du « Globbing étendu »
Cependant, word
correspond au pattern
en utilisant les règles de « Pathname Expansion ».
Et le « Extended Globbing » ici, ici et ici permet l'utilisation de modèles alternés ("|").
Cela fonctionne aussi :
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
Contenu de la chaîne
Le script de test suivant montre que le modèle qui correspond à toutes les lignes contenant soit foo
ou bar
n'importe où est '*$(foo|bar)*'
ou les deux variables $s1=*foo*
et $s2=*bar*
Scénario de test :
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_