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

168

Estoy tratando de crear una secuencia de comandos 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.com
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 aconsejar cuándo usar:

  • corchetes simples y dobles
  • paréntesis

?

HTF
fuente
3
¿Podría ser más preciso en cuanto a lo que "no funciona"? ¿Tiene un mensaje de error específico o simplemente no proporciona el resultado esperado?
Julien Vivenot
En realidad estaba recibiendo "operador unitario esperado" por lo que parece citar ayuda
HTF
-aTiene duplicidad. Cuando se usa con el testcomando de estilo de shell Bourne , también conocido como [, significa and. Cuando se usa como una expresión condicional , se está probando para ver si existe un archivo. Sí, es confuso, es mejor evitarlo.
cdarke

Respuestas:

254

Lo que tienes debe funcionar, a menos que ${STATUS}esté vacío. Probablemente sería mejor hacer:

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

o

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

Es difícil de decir, ya que no nos ha mostrado exactamente qué está mal con su script.

Opinión personal: nunca usar [[. Suprime mensajes de error importantes y no es portátil a diferentes shells.

William Pursell
fuente
2
Si STATUSestá vacío, el código de @HTF habría fallado -ne: unary operator expected. En su caso, fallará integer expression expected, ¿no?
Julien Vivenot
1
Entiendo que. Pero resalta el problema que $STATUSpodría estar vacío y sugiere una solución (citando). Su solución aún falla con un vacío STATUS, eso es todo lo que quise decir.
Julien Vivenot
1
@jvivenot Tienes un punto. (Mi respuesta a su comentario se hizo antes de editar su comentario, cuando su comentario simplemente decía "el código ... hubiera fallado". Se debe usar una solución simple ${STATUS:-0". Se editará.
William Pursell
Lo sentimos, tu edición aún no funciona. Por ejemplo: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo foono se emite foo, aunque debería (vacío es diferente de 13). Lo que sugirió por primera vez, se ${STATUS:-0}ve mucho mejor.
Julien Vivenot
@jvivenot El uso ${STATUS:-0}fallará si STATUS=foo, pero ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo foofunciona. En mi opinión, es mejor evitar -eqy usar !=.
William Pursell
28

Prueba esto:

if [ $STATUS -ne 200 -a "$STRING" != "$VALUE" ]; then
BrenanK
fuente
trabajó para mi. Creo que puede haber más de una forma, pero estoy satisfecho con esto por ahora.
Kushal Ashok
27

Prueba esto:

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

o

if [ ${STATUS} -ne 100 ] && [ "${STRING}" = "${VALUE}" ]
AnshBikram
fuente
más para un ejemplo más limpio
Pawel Cioch
12

Citar:

El operador "-a" tampoco funciona:

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

Para una explicación más elaborada: [y ]no son palabras reservadas de Bash. La ifpalabra clave introduce un condicional para ser evaluado por un trabajo (el condicional es verdadero si el valor de retorno del trabajo es 0o falso en caso contrario).

Para pruebas triviales, existe el testprograma ( man test).

Como algunos encuentran líneas como if test -f filename; then foo bar; fi, etc. molestas, en la mayoría de los sistemas encuentras un programa llamado [que de hecho es solo un enlace simbólico al testprograma. Cuando testse llama como [, debe agregar ]como último argumento posicional.

Entonces if test -f filenamees básicamente lo mismo (en términos de procesos generados) que if [ -f filename ]. En ambos casos, el testprograma se iniciará y ambos procesos deberían comportarse de manera idéntica.

Aquí está su error: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]analizará if+ algún trabajo, el trabajo es todo excepto el ifpropio. El trabajo es solo un comando simple (Bash habla por algo que resulta en un solo proceso), lo que significa que la primera palabra ( [) es el comando y el resto sus argumentos posicionales. Hay argumentos restantes después del primero] .

Además, no [[es una palabra clave Bash, pero en este caso solo se analiza como un argumento de comando normal, porque no está al frente del comando.

Jo So
fuente