Zaneguj warunek if w skrypcie bash

162

Jestem nowy w bashu i utknąłem na próbie zanegowania następującego polecenia:

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

Dzieje się tak, jeśli warunek zwraca wartość true, jeśli mam połączenie z Internetem. Chcę, żeby stało się to na odwrót, ale umieszczanie w !dowolnym miejscu nie wydaje się działać.

Sudh33ra
źródło
3
Gdzie to położyłeś? if ! [[ ...działa
ten drugi facet
1
możesz też użyć tego w ten sposób: wget your_xxxx_params || (echo „oh oh” && wyjście 1)
AKS
2
> wywołanie podpowłoki tylko po to, aby wyświetlić błąd
tijagi,

Odpowiedzi:

227

Możesz wybrać:

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

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

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

! odwraca odpowiednio zwrot następującego wyrażenia.

Cyrus
źródło
9
czy potrzebne są podwójne nawiasy? dlaczego?
Alexander Mills,
1
@AlexanderMills: Można to zrobić na kilka sposobów. Z podwójnymi lub pojedynczymi nawiasami lub z testpoleceniem:if test $? -ne 0; then
Cyrus
4
Ta odpowiedź jest niepotrzebnie rozwlekła. ifoczekuje instrukcji o wartości 0 lub 1, więc możesz użyć samego polecenia i odwrócić je:if ! wget ...; then ...; fi
Nils Magnus
87

Lepszy

if ! wget -q --spider --tries=10 --timeout=20 google.com
then
  echo 'Sorry you are Offline'
  exit 1
fi
Steven Penny
źródło
1
Ważne: zachowaj spację między !następującą komendą, w przeciwnym razie wykonasz rozwinięcie historii. unix.stackexchange.com/questions/3747/…
Roland
2
Steven, dlaczego masz tylko 1 reputację?
Roland
8

Jeśli czujesz się leniwy, oto zwięzła metoda obsługi warunków za pomocą ||(lub) i &&(i) po operacji:

wget -q --tries=10 --timeout=20 --spider http://google.com || \
{ echo "Sorry you are Offline" && exit 1; }
Cole Tierney
źródło
8
W prawdziwych skryptach należy zmienić polecenie &&after echo na a ;. Powodem tego jest to, że jeśli dane wyjściowe są przekierowywane do pliku na pełnym dysku, echozwróci błąd i exitnigdy się nie uruchomi. Prawdopodobnie nie jest to pożądane zachowanie.
Score_Under
lub możesz użyć, set -ea niepowodzenie i echotak wyjdzie ze skryptu
Jakub Bochenski
4

Ponieważ porównujesz liczby, możesz użyć wyrażenia arytmetycznego , które pozwala na prostszą obsługę parametrów i porównanie:

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

Zwróć uwagę, że zamiast tego -nemożesz po prostu użyć !=. W kontekście arytmetycznym nie musimy nawet poprzedzać $parametrów, tj.

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

działa doskonale. Nie dotyczy to jednak $?specjalnego parametru.

Ponadto, ponieważ (( ... ))ocenia wartości niezerowe jako prawdziwe, tj. Zwraca stan 0 dla wartości niezerowych i zwracany stan 1, w przeciwnym razie moglibyśmy skrócić do

if (( $? )); then

ale może to zmylić więcej osób, niż warte są zapisane naciśnięcia klawiszy.

(( ... ))Konstrukt jest dostępny w konsoli, ale nie jest to wymagane w opisie powłoki POSIX (wymienione jako możliwe przedłużenie, choć).

Biorąc to wszystko pod uwagę, lepiej $?moim zdaniem unikać w ogóle, jak w odpowiedzi Cole'a i odpowiedzi Stevena .

Benjamin W.
źródło
Jesteś pewien (( ... ))? Dokumentacja programistów POSIX - Polecenia złożone
David C. Rankin
@ David C.Rankin Och, nie znalazłem tego! Więc jest wspomniany jako rozszerzenie, ale nie jest wymagane. Poprawię.
Benjamin W.
1
Tak, ten zawsze mnie też dopadł. To z pewnością ułatwia życie w skorupie:)
David C. Rankin
4

Możesz użyć nierównego porównania -nezamiast -eq:

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