Negar si la condición en script bash

163

Soy nuevo en bash y estoy atascado al tratar de negar el siguiente comando:

wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -eq 0 ]]; then
        echo "Sorry you are Offline"
        exit 1

Esto si la condición devuelve verdadero si estoy conectado a internet. Quiero que suceda al revés, pero poner en !cualquier lugar no parece funcionar.

Sudh33ra
fuente
3
¿Donde lo pusiste? if ! [[ ...funciona
ese otro tipo
1
También puede usarlo de esta manera: wget your_xxxx_params || (echo "oh oh" && salida 1)
AKS
2
> llamar a una subshell solo para generar un error
tijagi

Respuestas:

227

Tu puedes elegir:

if [[ $? -ne 0 ]]; then       # -ne: not equal

if ! [[ $? -eq 0 ]]; then     # -eq: equal

if [[ ! $? -eq 0 ]]; then

! invierte el retorno de la siguiente expresión, respectivamente.

Ciro
fuente
9
¿son necesarios los corchetes dobles? ¿porqué es eso?
Alexander Mills
1
@AlexanderMills: Hay varias formas de hacer esto. Con corchetes dobles o simples o con testcomando:if test $? -ne 0; then
Cyrus
44
Esta respuesta es innecesariamente detallada. ifespera una declaración que sea 0 o 1, por lo que puede usar el comando en sí mismo e invertirlo:if ! wget ...; then ...; fi
Nils Magnus
87

Mejor

if ! wget -q --spider --tries=10 --timeout=20 google.com
then
  echo 'Sorry you are Offline'
  exit 1
fi
Steven Penny
fuente
1
Importante: mantenga un espacio entre el !siguiente comando y, de lo contrario, realizará una expansión del historial. unix.stackexchange.com/questions/3747/…
Roland
2
Steven, ¿por qué solo tienes 1 reputación?
Roland
8

Si se siente flojo, aquí hay un método conciso para manejar las condiciones usando ||(o) y &&(y) después de la operación:

wget -q --tries=10 --timeout=20 --spider http://google.com || \
{ echo "Sorry you are Offline" && exit 1; }
Cole Tierney
fuente
8
En los scripts de la vida real, debe cambiar el &&comando after the echo a a ;. La razón de esto es que si la salida se redirige a un archivo en un disco lleno, echodevolverá el error y exitnunca se disparará. Probablemente este no sea el comportamiento que desea.
Score_Under
o puede usar set -ey fallar echosaldrá del script de todos modos
Jakub Bochenski
4

Como está comparando números, puede usar una expresión aritmética , que permite un manejo más simple de los parámetros y la comparación:

wget -q --tries=10 --timeout=20 --spider http://google.com
if (( $? != 0 )); then
    echo "Sorry you are Offline"
    exit 1
fi

Observe cómo en lugar de -ne, simplemente puede usar !=. En un contexto aritmético, ni siquiera tenemos que anteponer los $parámetros, es decir,

var_a=1
var_b=2
(( var_a < var_b )) && echo "a is smaller"

Funciona perfectamente bien. Sin embargo, esto no se aplica al $?parámetro especial.

Además, dado que (( ... ))evalúa los valores distintos de cero a verdadero, es decir, tiene un estado de retorno de 0 para valores distintos de cero y un estado de retorno de 1 de lo contrario, podríamos acortarlo a

if (( $? )); then

pero esto podría confundir a más personas de lo que valen las pulsaciones de teclas guardadas.

La (( ... ))construcción está disponible en Bash, pero no es requerida por la especificación de shell POSIX (aunque mencionada como posible extensión).

Todo esto se dice, es mejor evitar $?por completo en mi opinión, al igual que en la respuesta de Cole y la respuesta de Steven .

Benjamin W.
fuente
¿Estás seguro (( ... ))? Referencia de programadores POSIX - Comandos compuestos
David C. Rankin
@ DavidC.Rankin ¡Oh, no encontré eso! Por lo tanto, se menciona como una extensión, pero no es obligatorio. Lo enmendaré.
Benjamin W.
1
Sí, ese siempre me tiene a mí también. Sin embargo:)
David C. Rankin el
4

Puede usar una comparación desigual en -nelugar de -eq:

wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -ne 0 ]]; then
    echo "Sorry you are Offline"
    exit 1
fi
davidhigh
fuente