Un operador "y" para una declaración "if" en Bash

Resuelto HTF asked hace 11 años • 5 respuestas

Estoy intentando crear un script Bash simple para verificar si el sitio web no funciona y por alguna razón el operador "y" no funciona:

#!/usr/bin/env bash

WEBSITE=domain.example
SUBJECT="$WEBSITE DOWN!"
EMAILID="[email protected]"
STATUS=$(curl -sI $WEBSITE | awk '/HTTP\/1.1/ { print $2 }')
STRING=$(curl -s $WEBSITE | grep -o "string_to_search")
VALUE="string_to_search"

if [ $STATUS -ne 200 ] && [[ "$STRING" != "$VALUE" ]]; then
    echo "Website: $WEBSITE is down, status code: '$STATUS' - $(date)" | mail -s "$SUBJECT" $EMAILID
fi

El operador "-a" tampoco funciona:

if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]

¿Podría también indicarnos cuándo utilizarlo?

  • corchetes simples y dobles
  • paréntesis

?

HTF avatar Nov 16 '12 07:11 HTF
Aceptado

Si $STATUSse expande a la cadena vacía, entonces if [ $STATUS -ne 200 ]no es válido porque es equivalente a if [ -ne 200 ], lo que debería generar un error similar a "-ne: se espera un operador unario".

El comando

if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]];

no es válido independientemente de la expansión de $STATUSporque está pasando [[y ]]como argumentos del [comando, pero [requiere que su último argumento sea la cadena literal ]. Probablemente sería mejor hacer:

if ! [ "${STATUS}" -eq 200 ] 2> /dev/null && [ "${STRING}" != "${VALUE}" ]; then ...

o

if [ "${STATUS}" != 200 ] && [ "${STRING}" != "${VALUE}" ]; then ...

En cada uno de estos, ]está el argumento final para la invocación de [, según sea necesario. El shell analiza &&y ;como tokens que finalizan el [comando, pero cadenas como -a, [[y ]]son solo cadenas que el shell pasa al comando. (En el primer caso, el shell lo trata 2> /dev/nullcomo un operador de redirección, por lo que esas cadenas no se pasan [como argumentos). Tenga en cuenta que utilizar -acomo argumento to como AND[ booleano se considera una mala práctica y debe evitarse.

[y [[son muy diferentes, pero la única diferencia entre [y testes que [requiere que su argumento final sea ]y testno lo es. (Algunos argumentarán que otra diferencia es que [es una función incorporada pero testno lo es, y aunque puede haber habido un momento en el pasado distante en el que algunos shells tenían [como función incorporada while testsiempre era una invocación de /bin/test, probablemente ese no haya sido el caso en cualquier caparazón común durante décadas). Otra solución razonable es:

if test "${STATUS}" != 200 && test "${STRING}" != "${VALUE}"; then ...

Opinión personal: nunca utilizar [[. Suprime mensajes de error importantes y no es portátil a diferentes shells. Además, como se ve por la existencia de esta pregunta, es confusa. Se puede argumentar que la confusión aquí es causada por la gramática del shell y el oscuro comportamiento de [, y estoy de acuerdo. [También es confuso. Puedes evitar mucha confusión si evitas ambos [[y [y siempre usas test.

William Pursell avatar Nov 16 '2012 00:11 William Pursell

Prueba esto:

if [ "${STATUS}" -ne 100 -a "${STRING}" = "${VALUE}" ]

o

if [ "${STATUS}" -ne 100 ] && [ "${STRING}" = "${VALUE}" ]
AnshBikram avatar Feb 23 '2016 07:02 AnshBikram