Mylące użycie & & i || operatory

Przeglądałem plik /etc/rc.d/init.d/sendmail (wiem, że jest to rzadko używane, ale ja „m przygotowuję się do egzaminu) i „trochę się pogubiłem co do operatorów && i ||. Czytałem już, gdzie można ich używać w instrukcjach, takich jak:

if [ test1 ] && [ test2 ]; then echo "both tests are true" elif [ test1 ] || [ test2 ]; then echo "one test is true" fi 

Jednak ten skrypt pokazuje instrukcje jednowierszowe, takie jak:

[ -z "$SMQUEUE" ] && SMQUEUE="QUEUE" [ -f /usr/sbin/sendmail ] || exit 0 

Wydaje się, że używają operatorów && i || w celu uzyskania odpowiedzi na podstawie testy, ale nie byłem w stanie znaleźć dokumentacji dotyczącej tego konkretnego zastosowania tych operatorów. Czy ktoś może wyjaśnić, co to robi w tym konkretnym kontekście?

Odpowiedź

Prawa strona && zostanie sprawdzone tylko wtedy, gdy kod zakończenia po lewej stronie wynosi zero (tj. prawda). || jest odwrotnie: obliczy prawą stronę tylko wtedy, gdy status wyjścia po lewej stronie jest różny od zera (tj. fałsz).

Możesz rozważyć [ ... ] jako program ze zwracaną wartością. Jeśli test wewnętrzny ma wartość true, zwraca zero; w przeciwnym razie zwraca wartość różną od zera.

Przykłady:

$ false && echo howdy! $ true && echo howdy! howdy! $ true || echo howdy! $ false || echo howdy! howdy! 

Dodatkowe uwagi:

Jeśli zrobisz which [, możesz zobaczyć, że [ faktycznie wskazuje na program! Zwykle nie jest to jednak ten, który działa w skryptach; uruchom type [, aby zobaczyć, co faktycznie jest uruchamiane. Jeśli chcesz spróbować użyć programu, podaj pełną ścieżkę, np. więc: /bin/[ 1 = 1.

Komentarze

  • Gdy widzisz ” X lub Y „, testujesz X. Jeśli ' jest prawdą, znasz już odpowiedź na ” X lub Y ” (to ' jest prawdziwe), więc nie ma potrzeby testowania Y. Jeśli tak ' prawda, nie ' nie znasz odpowiedzi na ” X lub Y „, więc musisz przetestować Y. Gdy zobaczysz ” X i Y ” , testujesz X. Jeśli ' jest fałszywe, znasz już odpowiedź na ” X i Y ” (it ' s fałsz), s o nie ma potrzeby testowania Y. Jeśli X jest prawdziwe, musisz przetestować Y, aby sprawdzić, czy ” X i Y ” jest prawda.
  • Zamiast ” jeśli lewa strona zwraca zero „, napisałbym „, jeśli stan wyjścia polecenia po lewej stronie ' wynosi zero „. Uważam, że ” zwraca ” nieco niejednoznaczne, ponieważ dane wyjściowe i stan wyjścia można uznać za ” zwracane wartości ”
  • Nie tylko możesz ” rozważyć [ ... ] być programem „, w wielu przypadkach jest . Zwykle jest ' w pliku /bin/[ lub /usr/bin/[.
  • C uznają to za bardzo zagmatwane. Tam 0 oznacza fałsz … Podczas gdy w skryptach powłoki 0 oznacza prawdę … Rozumiem.
  • @Calmarius Jeśli ' ponownie użyłeś do C, pomyśl o return statusy, a nie wartości logiczne, gdzie return 0 oznacza sukces.

Odpowiedź

Oto moja ściągawka:

  • „A; B „Uruchom A, a następnie B, niezależnie od powodzenia A
  • „ A & & B „B” jeśli A się powiodło
  • „A || B „Uruchomienie B, jeśli A nie powiodło się
  • „ A & „Uruchomienie A w tle.

Komentarze

  • Istnieją ' kilka interesujących paralel z rachunkiem lambda, pokazanych tutaj w działającym JavaScript (zdefiniuj zmienne w kolejności); ” left (aka true) „: (a => b => a). ” right (inaczej false) „: (a => b => b). ” A; B ” „, a następnie ” (a => b => (() => b())(a())). ” A & & B ” ” jeśli bez else (kiedy) ” (a => b => a()(() => right)(b)).” A || B ” ” else bez if (chyba że) ” (a => b => a()(b)(() => right)). ” a & & b || c ” ” ifThenElse ” (a => b => c => (unless(when(a)(b))(c))()) .
  • zauważ, że w bash lewe to analogiczne 0 / pusty ciąg, prawe analogiczne to wszystko inne.
  • A co z pojedynczym pionowym paskiem?

Odpowiedz

aby rozwinąć odpowiedź @ Shawn-j-Goff „z góry, && to logiczne ORAZ, a || to logiczne LUB.

Zobacz część Zaawansowany przewodnik po skryptach Bash. Część zawartości z linku w celach informacyjnych dla użytkownika, jak poniżej.

& & AND

if [ $condition1 ] && [ $condition2 ] # Same as: if [ $condition1 -a $condition2 ] # Returns true if both condition1 and condition2 hold true... if [[ $condition1 && $condition2 ]] # Also works. # Note that && operator not permitted inside brackets #+ of [ ... ] construct. 

|| LUB

if [ $condition1 ] || [ $condition2 ] # Same as: if [ $condition1 -o $condition2 ] # Returns true if either condition1 or condition2 holds true... if [[ $condition1 || $condition2 ]] # Also works. # Note that || operator not permitted inside brackets #+ of a [ ... ] construct. 

Odpowiedź

Z własnego doświadczenia korzystam & & an d || aby zredukować instrukcję if do jednej linii.

Powiedzmy, że szukamy pliku o nazwie /root/Sample.txt, to tradycyjna iteracja w powłoce wyglądałaby następująco:

if [ -f /root/Sample.txt ] then echo "file found" else echo "file not found" fi 

Te 6 wierszy można zredukować do jednej linii:

[[ -f /root/Sample.txt ]] && echo "file found" || echo "file not found" 

Podczas wykonywania kilku iteracji w celu ustawienia zmiennych lub do tworzenia plików itp., życie jest łatwiejsze, a skrypt wygląda lepiej, używając pojedynczej linii if function, jedyną wadą jest to, że implementacja wielu poleceń z jednej iteracji staje się nieco trudniejsza, jednak można korzystać z funkcji.

Komentarze

  • To jest fajne. Przypomina mi kod objc (a == b)? val = 1: val = 2;
  • Jak mogę użyć tego polecenia, gdy chcę uruchomić proces w tle z ” & „? Otrzymuję błąd składni dla ./someScript.sh & && echo 'ok' || echo 'ko'
  • W postaci: foo && bar || baz, if foo zakończy się pomyślnie, a następnie bar nie powiedzie się, baz zostanie uruchomiony, więc różni się nieco od if.
  • Muszę zauważyć, że możliwe jest wykonanie kilku poleceń z rzędu w nawiasach {}, używając && lub ||, na przykład: pidof udpxy > /dev/null 2>&1 && echo "udpxy is up!" || { echo "udpxy is down!"; /etc/init.d/udpxy restart; }. Warto również wspomnieć, że if..then..else jest bardziej niezawodnym ” narzędziem do rozpoznawania ” typu true / fałszywe warunki niż użycie && i ||.

Odpowiedź

Istnieje pojęcie „krótkiego skrawania”.

Podczas oceny (expr1 && expr2)expr2 jest oceniane tylko wtedy, gdy exp1 ma wartość„ prawda ”. Dzieje się tak, ponieważ expr1 ORAZ expr2 muszą być prawdziwe, aby (expr1 && expr2) było prawdziwe. Jeśli expr1 ma wartość „false”, expr2 NIE jest oceniane (skrót), ponieważ (expr1 && expr2) jest już „flase”.

Załóżmy, że plik F1 istnieje & plik F2 nie istnieje:

( [ -s F1 ] && echo "File Exists" ) # will print "File Exists" - no short cut ( [ -s F2 ] && echo "File Exists" ) # will NOT print "File Exists" - short cut

Podobnie dla || (lub) – ale krótkie cięcie jest odwrócone.

Komentarze

  • Logika jest zwykle określana jako ” krótkie spięcie „. ' nigdy nie widziałem używanego wyrażenia ” krótkie cięcie „. Wspominam o tym, aby pomóc w znalezieniu odniesień.

Odpowiedź

Przykłady w odpowiedzi Shawna J. Goffa są poprawne, ale wyjaśnienie jest odwrotne. Sprawdź:

Prawa strona & & zostanie oceniony tylko wtedy, gdy status wyjścia po lewej stronie to NONZERO. || jest odwrotnie: ocenia prawą stronę tylko wtedy, gdy status wyjścia po lewej stronie wynosi ZERO.

Komentarze

  • Wiesz, że dla powłok zero kod zakończenia zwraca wartość prawda , a zatem niezerowy kod zakończenia po lewej stronie && powoduje, że całe wyrażenie zwraca false ?
  • Ktoś nie zatwierdził twoich zmian, ponieważ nie była to Twoja odpowiedź.Jeśli uważasz, że jakaś odpowiedź jest niepoprawna, powinieneś ją zlekceważyć i ewentualnie zostawić komentarz; jeśli uważasz, że wymaga zmiany, zostaw komentarz. Edycja służy do poprawiania gramatyki, formatowania i błędów ortograficznych, które nie zmieniają znaczenia odpowiedzi.
  • @countermode I ' m przepraszam, masz rację, Myślałem, że w Linuksie zero = false i nonzero = true (jak w C i wielu innych językach / środowiskach / platformach). Przepraszam za nieporozumienie.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *