Estoy tratando de usar una variable que consta de diferentes cadenas separadas con un |
como un case
prueba de declaraciones Por ejemplo:
string=""foo"|"bar""
read choice
case $choice in
$string)
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Quiero poder escribir foo
o bar
y ejecuta la primera parte del case
declaración. Sin embargo, tanto foo
y bar
llévame al segundo:
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Usando "$string"
en lugar de $string
No hace diferencia. Tampoco usar string="foo|bar"
.
Sé que puedo hacerlo de esta manera:
case $choice in
"foo"|"bar")
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Puedo pensar en varias soluciones, pero me gustaría saber si es posible usar una variable como un case
condición en bash. ¿Es posible y, de ser así, cómo?
Respuesta aceptada:
El manual de bash dice:
caso palabra en [ [(] patrón [ | patrón ] … ) lista;; ] … esac
Cada patrón examinado se expande usando expansión de tilde, expansión de parámetros y variables, sustitución aritmética, sustitución de comandos y sustitución de procesos.
Sin «expansión de nombre de ruta»
Por lo tanto:un patrón NO se expande con «Expansión de nombre de ruta».
Por lo tanto:un patrón NO puede contener “|” en el interior. Solo:se podrían unir dos patrones con el “|”.
Esto funciona:
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
Uso de «Globbing extendido»
Sin embargo, word
coincide con pattern
utilizando las reglas de «Expansión de nombre de ruta».
Y «Extendido Globbing» aquí, aquí y aquí permite el uso de patrones alternos (“|”).
Esto también funciona:
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
Contenido de cadena
El siguiente script de prueba muestra que el patrón que coincide con todas las líneas que contienen foo
o bar
cualquier lugar es '*$(foo|bar)*'
o las dos variables $s1=*foo*
y $s2=*bar*
Guión de prueba:
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_