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
$g
entre comillas dobles; Esa es una buena práctica, en general. Estrictamente, los paréntesis no son necesarios porque la precedencia de-a
y lo-o
hace correcto incluso sin ellos.Tenga en cuenta que los operadores
-a
y-o
son parte de la especificación POSIX paratest
, alias[
, principalmente para la compatibilidad con versiones anteriores (ya que formaban parte de latest
7a 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-a
y-o
con 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
autoconf
herramienta 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
then
bloques.fuente
-a
realidad 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-a
y-o
lograr 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_inodes
está 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
/else
y tener el código entrethen
yfi
poner una función para evitar repetirlo. En casos muy simples, podría usar unacase
declaración con;&
fallthrough (en Bash 4).Usar
/bin/bash
lo 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