Negar se a condição no script bash

162

Sou iniciante no bash e estou tentando tentar negar o seguinte comando:

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

Esta condição se retorna verdadeira se eu estiver conectado à Internet. Eu quero que isso aconteça ao contrário, mas colocar em !qualquer lugar não parece funcionar.

Sudh33ra
fonte
3
Onde é que puseste? if ! [[ ...funciona
esse outro cara
1
você também pode usá-lo desta maneira: wget your_xxxx_params || (eco "oh oh" && exit 1)
AKS
2
> Chamar um subshell apenas para a saída de um erro
tijagi

Respostas:

227

Você pode escolher:

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

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

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

! inverte o retorno da seguinte expressão, respectivamente.

Cyrus
fonte
9
são necessários colchetes duplos? por que é que?
Alexander Mills
1
@ AlexanderMills: Existem várias maneiras de fazer isso. Com colchetes duplos ou simples ou com testcomando:if test $? -ne 0; then
Cyrus
4
Esta resposta é desnecessária e detalhada. ifespera uma declaração que seja 0 ou 1, para que você possa usar o próprio comando e invertê-lo:if ! wget ...; then ...; fi
Nils Magnus
87

Melhor

if ! wget -q --spider --tries=10 --timeout=20 google.com
then
  echo 'Sorry you are Offline'
  exit 1
fi
Steven Penny
fonte
1
Importante: mantenha um espaço entre o !comando a seguir e, caso contrário, você estará fazendo uma expansão do histórico. unix.stackexchange.com/questions/3747/…
Roland em
2
Steven, por que você tem apenas 1 reputação?
Roland
8

Se você estiver com preguiça, aqui está um método conciso de lidar com as condições usando ||(ou) e &&(e) após a operação:

wget -q --tries=10 --timeout=20 --spider http://google.com || \
{ echo "Sorry you are Offline" && exit 1; }
Cole Tierney
fonte
8
Nos scripts da vida real, você deve alterar o &&comando after echo para a ;. A razão para isso é que, se a saída estiver sendo redirecionada para um arquivo em um disco completo, a echofalha retornará e exitnunca será acionada. Este provavelmente não é o comportamento que você deseja.
Score_Under
ou você pode usar set -ee não echovai sair do script de qualquer maneira
Jakub Bochenski
4

Como você está comparando números, pode usar uma expressão aritmética , que permite um tratamento mais simples dos parâmetros e comparação:

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

Observe como, em vez de -ne, você pode apenas usar !=. Em um contexto aritmético, nem precisamos preceder $aos parâmetros, ou seja,

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

funciona perfeitamente bem. Isso não se aplica ao $?parâmetro especial, no entanto.

Além disso, como (( ... ))avalia valores diferentes de zero como true, ou seja, possui um status de retorno 0 para valores diferentes de zero e um status de retorno 1, caso contrário, poderíamos reduzir para

if (( $? )); then

mas isso pode confundir mais pessoas do que valem as teclas salvas.

A (( ... ))construção está disponível no Bash, mas não é exigida pela especificação do shell POSIX (mencionada como possível extensão).

Isso tudo foi dito, é melhor evitar $?por completo na minha opinião, como na resposta de Cole e resposta de Steven .

Benjamin W.
fonte
Você tem certeza (( ... ))? Referência dos programadores POSIX - Comandos compostos
David C. Rankin
@ DavidC.Rankin Oh, eu não achei isso! Portanto, é mencionado como uma extensão, mas não é obrigatório. Eu vou alterar.
Benjamin W.
1
Sim, esse sempre me pegou também. Com certeza faz a vida mais fácil com casca embora:)
David C. Rankin
4

Você pode usar comparação desigual em -nevez 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
fonte