Quiero representar múltiples condiciones como esta:
if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]
then
echo abc;
else
echo efg;
fi
pero cuando ejecuto el script, muestra
syntax error at line 15: `[' unexpected,
donde la línea 15 es la que muestra si ...
¿Qué hay de malo en esta condición? Supongo que algo está mal con el ().

test([) y no por el shell. El shell evalúa solo el estado de salida de[.Respuestas:
Técnica clásica (metacaracteres de escape):
He incluido las referencias
$gentre comillas dobles; Esa es una buena práctica, en general. Estrictamente, los paréntesis no son necesarios porque la precedencia de-ay lo-ohace correcto incluso sin ellos.Tenga en cuenta que los operadores
-ay-oson parte de la especificación POSIX paratest, alias[, principalmente para la compatibilidad con versiones anteriores (ya que formaban parte de latest7a edición de UNIX, por ejemplo), pero POSIX los marca explícitamente como 'obsoletos'. Bash (ver expresiones condicionales ) parece evitar los significados clásicos y POSIX para-ay-ocon sus propios operadores alternativos que toman argumentos.Con un poco de cuidado, puede utilizar el
[[operador más moderno , pero tenga en cuenta que las versiones en Bash y Korn Shell (por ejemplo) no necesitan ser idénticas.Ejemplo de ejecución, utilizando Bash 3.2.57 en Mac OS X:
No necesita citar las variables
[[como lo hace[porque no es un comando separado de la misma manera que lo[es.Lo hubiera pensado así. Sin embargo, hay otra alternativa, a saber:
De hecho, si lee las pautas de 'shell portátil' para la
autoconfherramienta o los paquetes relacionados, esta notación, usando '||' y '&&', es lo que recomiendan. Supongo que incluso podrías ir tan lejos como:Donde las acciones son tan triviales como hacer eco, esto no es malo. Cuando el bloque de acción que se repetirá es de varias líneas, la repetición es demasiado dolorosa y es preferible una de las versiones anteriores, o debe ajustar las acciones en una función que se invoca en los diferentes
thenbloques.fuente
-arealidad tiene mayor prioridad que-o(a diferencia&&y||en el shell, sin embargo, dentro de losbash[[ ... ]]condicionales ,&&también tiene mayor prioridad que||). Si desea evitar-ay-olograr la máxima robustez y portabilidad, que sugiere la página de manual POSIX, también puede usar subcapas para agrupar:if ([ $g -eq 1 ] && [ "$c" = "123" ]) || ([ $g -eq 2 ] && [ "$c" = "456" ])if test "$g" -eq 1 -a "$c" = "123" || test "$g" -eq 2 -a "$c" = "456"; then ...&&o||también es preferible, ya que se comporta más como condicionales en otros idiomas y le permite cortocircuitar las condiciones. Por ejemplo:if [ -n "${check_inodes}" ] && [ "$(stat -f %i "/foo/bar")" = "$(stat -f %i "/foo/baz")" ]. Al hacerlo de esta manera, sicheck_inodesestá vacío, evita dos llamadas astat, mientras que una condición de prueba más grande y compleja debe procesar todos los argumentos antes de ejecutarla (lo que también puede generar errores si olvida ese comportamiento).En Bash:
fuente
bash. Como comentario aparte: en este caso particular, los paréntesis ni siquiera son necesarios, porque los condicionales internos en realidad tienen mayor prioridad que , a diferencia de los condicionales externos .[[ ... ]]&&||if/elsey tener el código entrethenyfiponer una función para evitar repetirlo. En casos muy simples, podría usar unacasedeclaración con;&fallthrough (en Bash 4).Usar
/bin/bashlo siguiente funcionará:fuente
Tenga cuidado si tiene espacios en sus variables de cadena y verifica su existencia. Asegúrese de citarlos correctamente.
fuente
fuente
{ ;}podría usarse en su lugar.En bash para la comparación de cadenas, puede usar la siguiente técnica.
Ejemplo:
fuente
fuente
También puede encadenar más de 2 condiciones:
fuente