Estoy tratando de utilizar una variable que consiste en diferentes cadenas separadas con una |
como una case
prueba de declaración. 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
ejecutar la primera parte de la case
declaración. Sin embargo, ambos foo
y bar
llévame al segundo:
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Usar en "$string"
lugar de $string
no hace ninguna diferencia. Tampoco el uso 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 case
condición en bash. ¿Es posible y, de ser así, cómo?
bash
shell-script
case
terdon
fuente
fuente
eval
opción de $ escapándose, los parens, el asterisco, el punto y coma y las nuevas líneas. Feo, pero "funciona".read
parte me detuvo. en mi opinión, la validación de entrada del usuario, que es lo que parece ser, loscase
patrones no deberían estar en la parte superior de la lista de evaluación, sino que deberían reducirse al*
patrón predeterminado de modo que los únicos resultados que lleguen allí sean garantizados aceptables. aún así, debido a que el problema es el orden de análisis / expansión, entonces una segunda evaluación podría ser lo que se requiere.Respuestas:
El manual de bash dice:
No «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 "|" dentro. Solo: dos patrones se pueden unir con el "|".
Esto funciona:
Usando «Globbing extendido»
Sin embargo,
word
sepattern
combina con el uso de las reglas de "Expansión del nombre de ruta".Y «Globbing extendido» aquí , aquí y, aquí permite el uso de patrones alternos ("|").
Esto también funciona:
Contenido de cadena
El siguiente script de prueba muestra que el patrón que coincide con todas las líneas que contienen
foo
o enbar
cualquier lugar es'*$(foo|bar)*'
o las dos variables$s1=*foo*
y$s2=*bar*
Script de prueba:
fuente
Puedes usar la
extglob
opción:fuente
@(foo|bar)
especial en comparación confoo|bar
? Ambos son patrones válidos que funcionan igual cuando se escriben literalmente.|
no es parte del patrónfoo|bar
, es parte de la sintaxis de lacase
declaración para permitir múltiples patrones en una cláusula.|
Sin embargo, es parte del patrón extendido.Necesita dos variables
case
porque la|
tubería o se analiza antes de que se expandan los patrones.Los patrones de shell en las variables también se manejan de manera diferente cuando se citan o no:
fuente
Si desea una solución alternativa compatible con el tablero, puede escribir:
Explicación: awk se usa para dividir "cadenas" y probar cada parte por separado. Si "choice" coincide con la parte probada actualmente p [i], el comando awk terminará con "exit" en la línea 11. Para la misma prueba, se utiliza el "caso" del shell (dentro de una llamada 'system') , según lo solicitado por terdon. Esto mantiene la posibilidad de modificar la prueba de "cadena", por ejemplo, a "foo * | bar" para que coincida también con "foooo" ("patrón de búsqueda"), según lo permita el "caso" del shell. Si, en cambio, preferiría expresiones regulares, podría omitir la llamada al "sistema" y utilizar "~" o "coincidencia" de awk.
fuente