Estoy tratando de utilizar una variable que consiste en diferentes cadenas separadas con una |como una caseprueba 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 fooo barejecutar la primera parte de la casedeclaración. Sin embargo, ambos fooy barllévame al segundo:
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Usar en "$string"lugar de $stringno 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 casecondición en bash. ¿Es posible y, de ser así, cómo?
bash
shell-script
case
terdon
fuente
fuente

evalopción de $ escapándose, los parens, el asterisco, el punto y coma y las nuevas líneas. Feo, pero "funciona".readparte me detuvo. en mi opinión, la validación de entrada del usuario, que es lo que parece ser, loscasepatrones 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,
wordsepatterncombina 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
fooo enbarcualquier lugar es'*$(foo|bar)*'o las dos variables$s1=*foo*y$s2=*bar*Script de prueba:
fuente
Puedes usar la
extglobopció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 lacasedeclaración para permitir múltiples patrones en una cláusula.|Sin embargo, es parte del patrón extendido.Necesita dos variables
caseporque 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