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_