Czy istnieje różnica między „&&” a „;” symbole w standardowym terminalu BASH?

56

Wydaje się, że oba sygnalizują BASH rozpoczęcie kolejnego polecenia po symbolach, ale czy istnieje wyraźna różnica?

Michael Terry
źródło

Odpowiedzi:

75

Dzięki tej linii:

command1 && command2

polecenie 2 zostanie wykonane, jeśli (i tylko wtedy) polecenie 1 zwróci status wyjścia zero, natomiast w tym wierszu:

command1 ; command2

zarówno polecenie1, jak i polecenie2 zostaną wykonane niezależnie. Średnik umożliwia wpisanie wielu poleceń w jednym wierszu.


źródło
1
Ciekawy! Pomyślałem, że może to być wygodniejszy sposób. Dziękuję Ci!
42

Możesz wypróbować różnicę dla siebie:

  1. ls /invalid/path && echo "hello!"
    ponieważ / nieprawidłowa / ścieżka nie istnieje, ls nie może wyświetlić listy katalogów. Nie powiedzie się komunikat o błędzie: „ls: / invalid / path: Brak takiego pliku lub katalogu”. Druga połowa polecenia (echo „Hello!”) Jest nigdy jeszcze stracony , ponieważ pierwsza połowa nie powiodło się.

  2. ls /invalid/path ; echo "hello!"
    Ten sam komunikat o błędzie pojawia się jak poprzednio, ale tym razem druga część jest wykonywana !
    ls: / invalid / path:
    Witaj w takim pliku lub katalogu !

Dlaczego to jest przydatne?
Załóżmy, że chcesz wyodrębnić plik o nazwie archive.tar.gz
Możesz użyć polecenia tar zxvf archive.tar.gz && rm archive.tar.gz.
Jeśli z jakiegoś powodu rozpakowanie archiwum nie powiedzie się, druga część nie zostanie wykonana! Możesz spróbować jeszcze raz.

Jeśli użyjesz ; w tej samej sytuacji archiwum jest usuwane i nie można spróbować ponownie.

Kenny Rasschaert
źródło
8

&&oznacza AND, że drugie polecenie zostanie wykonane tylko wtedy, gdy pierwsze zwróci prawdę (bez błędów).

Ward Muylaert
źródło
1
&& to „następnie” (nie „i”) ... zobacz moją odpowiedź
Peter.O
2
@ fred Powiedziałbym, że to „i” z oceną zwarcia - jeśli pierwsza część jest nieprawdziwa, wie, że całkowity wynik musi być fałszywy, więc pomija drugą część. Ale zgódź się, że myślenie o nim jako „wtedy” rzadko robi dużą różnicę w tym kontekście.
jg-faustus
2
@fred Chociaż koncepcyjnie może być łatwiej to zrozumieć w ten sposób, nie zgadzam się z twoim stwierdzeniem. Chodzi o to, że przy każdym AND wykonaniu drugi parametr staje się nieistotny, jeśli pierwszy jest równy, falsea zatem kod bazowy zostaje zoptymalizowany w celu odroczenia oceny drugiego parametru, dopóki nie dowie się, jaki jest pierwszy.
Ward Muylaert
2
@fred Nie jestem pewien, jaki punkt ten przykład próbuje zrobić. &&jest tylko operatorem binarnym, funkcją. Jedyną „specjalną” rzeczą jest to, że jest to notacja infiksowa (która i tak jest standardem dla większości tego rodzaju operatorów) i opóźnione wykonanie drugiego operandu. Że opóźnia wykonanie rzeczywiście daje mu zdolność do wykorzystania jako coś, co może być postrzegane jako koncepcyjnie ifoświadczenia w tym kontekście , ale nie zabrać z faktu, że to pierwotnie zamierzonego użycia jest w zasięgu warunkowego o rzeczywistej ifoświadczenia. Użycie tutaj jest bardziej „hackowaniem”.
Ward Muylaert
3
@fred Oczywiście nie jest to operator trójskładnikowy, to po prostu następstwo dwóch operacji a && b || c = (a && b) || c. Prosta kolejność oceny. Naprawdę nie ma w tym żadnej tajemnicy. Gdybyś napisał je jak typowe funkcje, po prostu wyglądałoby or(and(a, b), c). Ta logika jest taka sama zarówno w ifwarunkowym, jak i podczas wprowadzania jej bezpośrednio do wiersza poleceń, ponieważ &&i ||operatorami , biorą dwa operandy i zwracają inny.
Ward Muylaert
8

Aktualizacja : Dodałem jako skrypt, aby wyróżnić niektóre z możliwych pułapek:

Ponieważ nikt inny nie wspomniał o „||”, zrobię to

Aktualizacja 2 : niektóre ważne przeredagowanie tutaj
&& jest jak „wtedy” wyrażenia „jeśli”, które odpowiada „prawda”

|| NIE jest jak „else” w stwierdzeniu „if”.
|| jest jak „wtedy” wyrażenia „jeśli”, które odpowiada na „fałsz”

Dokładniej, && testuje $? zwraca wartość poprzednio ostatnio wykonanej instrukcji i przekazuje kontrolę do instrukcji lub podpowłoki bezpośrednio po && ... przekazuje kontrolę tylko, jeśli $? jest prawdziwy.

|| jest podobny i często widuje się po instrukcji &&, ale testuje ona na fałszywą wartość zwracaną ($?) z poprzednio ostatnio wykonanej instrukcji ... Uwaga! , Nota Bene! Uwaga: jeśli poprzednia instrukcja jest instrukcją &&, która ponownie sprawdza fałsz, gdy spodziewasz się, że jest to prawda, to || zareaguje na fałsz, więc mieszanie obu na tej samej linii może być ryzykowne

Głównym punktem, który próbuję zrobić, jest błąd, który popełniłem. tj .:
## [[warunek]] i&A || B
jest nie nie zachowuje się jak C / C ++ stylu trójskładnikowego. tj .:
// (warunek)? Odp .: B
Zobacz poniższy skrypt, aby zobaczyć przykłady „nieoczekiwanych” wyników z „A”

Test podstawowy oraz && i || instrukcja musi znajdować się w tym samym wierszu ...


Uruchom ten skrypt, aby zobaczyć, co może się nie powieść podczas używania && i || Ostatnio wykonywane oświadczenie nie może być jeden oczekujesz ..

[[warunek]] && echo Hello || echo Pożegnanie .... jest zwykle bezpieczne,
ponieważ dobrze uformowane echo zwróci prawdę.
ale co z dostępem do pliku, który nie wychodzi?

#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR  contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo  ======
 ((1==1)) && echo  " ((1==1)) rc=$? ..&&.. condition is true" || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && echo "  \$0  0   rc=$? ..&&.. condition is true" || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && echo  " ((1!=1)) rc=$? ..&&.. condition is true" || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && echo "  \$0  1   rc=$? ..&&.. condition is true" || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo  ======
 ((1==1)) || echo  " ((1==1)) rc=$? ..||.. condition is true" && echo  " ((1==1)) rc=$? ..&&.. condition is false"
  $0  0   || echo "  \$0  0   rc=$? ..||.. condition is true" && echo "  \$0  0   rc=$? ..&&.. condition is false"
 ((1!=1)) || echo  " ((1!=1)) rc=$? ..||.. condition is true" && echo  " ((1!=1)) rc=$? ..&&.. condition is false"
  $0  1   || echo "  \$0  1   rc=$? ..||.. condition is true" && echo "  \$0  1   rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"

exit 

Peter.O
źródło
1

próbować

false && echo „hello”

i

fałszywe ; echo „cześć”

Zobacz różnicę

Petrie Wong
źródło
0

Polecenie (funkcja, w przypadku skryptu) po &&jest wykonywane w zależności od parametru RETVAL pierwszego polecenia (funkcja, w przypadku skryptu). Zmusza pierwsze polecenie do zwrócenia wartości 0, jeśli zakończy się powodzeniem. Możemy sprawdzić wartość zwracaną, aby wykonać dalsze polecenia.

theTuxRacer
źródło