Técnica clásica (metacaracteres de escape):
if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
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 para test
, alias [
, principalmente para la compatibilidad con versiones anteriores (ya que formaban parte de la test
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.
for g in 1 2 3
do
for c in 123 456 789
do
if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
then echo "g = $g; c = $c; true"
else echo "g = $g; c = $c; false"
fi
done
done
Ejemplo de ejecución, utilizando Bash 3.2.57 en Mac OS X:
g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false
No necesita citar las variables [[
como lo hace [
porque no es un comando separado de la misma manera que lo [
es.
¿No es una pregunta clásica?
Lo hubiera pensado así. Sin embargo, hay otra alternativa, a saber:
if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
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:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
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.
test
([
) y no por el shell. El shell evalúa solo el estado de salida de[
.