Pracuję z Bash 3 i próbuję tworzą warunek. W C / C ++ jest to banalnie proste: ((A || B) && C). W Bash okazuje się, że tak nie jest (myślę, że autorzy Git musieli wnieść ten kod, zanim przeszli do innych przedsięwzięć). 
 To nie działa. Zauważ, że <0 or 1> nie jest literałem ciągu; oznacza 0 lub 1 (generalnie pochodzi z grep -i). 
A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eqe "0" ]; then ... fi 
Wynik:
line 322: syntax error near unexpected token `[[" 
Następnie próbowałem:
A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ ([ "$A" -eq "0" ]) || ([ "$B" -ne "0" ]) ] && [ "$C" -eq "0" ]; then ... fi 
skutkuje:
line 322: syntax error near unexpected token `[[" 
Częścią problemu jest to, że wyniki wyszukiwania są trywialnymi przykładami, a nie bardziej złożonymi przykładami ze złożonymi warunkami warunkowymi.
 Jak wykonać proste ((A || B) && C) w Bash? 
Jestem gotowy, aby go po prostu rozwinąć i powtórzyć te same polecenia w wielu blokach:
A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ "$A" -eq "0" ] && [ "$C" -eq "0" ]; then ... elif [ "$B" -ne "0" ] && [ "$C" -eq "0" ]; then ... fi 
Odpowiedź
Składnia bash nie jest podobna do C, nawet jeśli niewielka jego część jest inspirowana przez C. Nie możesz po prostu spróbować napisać kodu w C i oczekiwać, że zadziała.
 Głównym celem powłoki jest wykonywanie poleceń. Polecenie otwartego nawiasu klamrowego [ to polecenie, które wykonuje pojedynczy test¹. Możesz nawet zapisać go jako test (bez końcowego nawiasu zamykającego). Operatory || i && są operatorami powłoki, łączą  polecenia , a nie testy. 
Więc kiedy piszesz
[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ] 
jest to analizowane jako
[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ] 
które jest tym samym, co
test [ "$A" -eq "0" || test "$B" -ne "0" ] && test "$C" -eq "0" 
Zwróć uwagę na niezrównoważone nawiasy? Tak, to nie jest dobre. Twoja próba użycia nawiasów ma ten sam problem: fałszywe nawiasy.
Składnia grupowania poleceń to nawiasy. Sposób, w jaki są analizowane nawiasy klamrowe, wymaga pełnego polecenia przed nimi, więc „będziesz musiał zakończyć polecenie wewnątrz nawiasów znakiem nowej linii lub średnika.
if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then … 
 Tam to alternatywny sposób, który polega na użyciu podwójnych nawiasów. W przeciwieństwie do nawiasów pojedynczych, nawiasy podwójne są specjalną składnią powłoki. Odgraniczają  wyrażenia warunkowe . W podwójnych nawiasach można używać nawiasów i operatorów, takich jak && i ||. Ponieważ podwójne nawiasy są składnią powłoki, powłoka wie, że gdy te operatory znajdują się w nawiasach, „stanowią część składni wyrażenia warunkowego, a nie zwykłej składni poleceń powłoki. 
if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then … 
Jeśli wszystkie twoje testy są numeryczne, istnieje jeszcze inny sposób, który ogranicza wyrażenia artystyczne . Wyrażenia arytmetyczne wykonują obliczenia na liczbach całkowitych przy użyciu składni bardzo podobnej do języka C.
if (((A == 0 || B != 0) && C == 0)); then … 
Możesz znaleźć mój nawias bash primer przydatne.
 [ może być używany w zwykłym sh. [[ i (( są specyficzne dla bash (oraz ksh i zsh). 
¹ Może również łączenie wielu testów z operatorami logicznymi, ale jest to niewygodne w użyciu i ma subtelne pułapki, więc nie będę tego wyjaśniał.
Komentarze
Odpowiedź
 Użyj [[: 
if [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]; then ... 
 Jeśli wolisz [, działa to: 
if [ \( "$A" -eq "0" -o "$B" -ne "0" \) -a "$C" -eq "0" ]; then ... 
Komentarze
- Dziękuję, Stephen. W moim przypadku użyłem twojego pierwszego przykładu w ten sposób … regex = ' ^ [0-9] + $ ' length = $ {#datearg} jeśli! [[$ datearg = ~ $ regex & & $ length -eq 8]]; następnie echo " błąd: To nie jest liczba dł. z 8 "; fi
 
Odpowiedź
 Użyj operatora -o zamiast swojego zagnieżdżone ||. Możesz także użyć -a, aby zastąpić & &, jeśli jest to potrzebne w innych wyciągach . 
 EXPRESSION1 -a EXPRESSION2 both EXPRESSION1 and EXPRESSION2 are true EXPRESSION1 -o EXPRESSION2 either EXPRESSION1 or EXPRESSION2 is true if [ "$A" -eq "0" -o "$B" -ne "0" ] && [ "$C" -eq "0" ]; then echo success;fi 
Komentarze
-  Dziękujemy. Natrafiłem na 
-ai-o, ale nie eksperymentowałem z nimi. Ktoś na Stack Overflow powiedział, żeby tego unikać. W większości się z nimi zgadzałem, ponieważ skrypt jest mniej czytelny przy ich użyciu. - … ale bardziej przenośny.
 -  @Kusalananda – Dzięki za ostrzeżenia o przenośności. Skrypt musi działać na systemach z Bash 2 do Bash 4. Czy 
[[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]będą miały z nimi problemy? -  Nie będzie żadnych problemów, o ile będziesz 
bashlub jakąkolwiek inną powłokę, która rozumie[[ ... ]]. - Wadą użycia -a jest to, że nie ' t zwarcie, jeśli pierwsze wyrażenie jest fałszywe. Więc jeśli polegasz na zwarciu, aby zapobiec uruchomieniu potencjalnie fatalnego drugiego wyrażenia, nie możesz użyć -a. Przykład: pastebin.com/zM77TXW1
 
[[ … ]]został dodany w bash 2.02.((…))został dodany w bashu 2.0.||i&&zmień z[na[[i((. Równe pierwszeństwo w[(użyj nawiasów, aby kontrolować kolejność oceny), ale & & ma wyższy priorytet w[[i((niż||(jak w C).[[ … ]]lub$((…))służą tylko do grupowania.