Több logikai operátor, ((A || B) & & C) és “ szintaktikai hiba váratlan token közelében ”

Én a Bash 3-zal dolgozom, és megpróbálok feltételeset alkotnak. A C / C ++ verzióban a halott egyszerű: ((A || B) && C). A Bash-ban kiderült, hogy nem így van (szerintem a Git-szerzőknek biztosan hozzájárultak ehhez a kódhoz, mielőtt más erőfeszítésekbe kezdtek volna).

Ez nem működik. Vegye figyelembe, hogy az <0 or 1> nem karakterlánc; 0 vagy 1 értéket jelent (általában grep -i forrásból származik).

A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eqe "0" ]; then ... fi 

Ennek eredménye:

line 322: syntax error near unexpected token `[[" 

Ezután megpróbáltam:

A=<0 or 1> B=<0 or 1> C=<0 or 1> if [ ([ "$A" -eq "0" ]) || ([ "$B" -ne "0" ]) ] && [ "$C" -eq "0" ]; then ... fi 

ennek eredménye:

line 322: syntax error near unexpected token `[[" 

A probléma része, hogy a keresési eredmények a triviális példák, és nem az összetett feltételekkel bonyolultabb példák.

Hogyan hajthatok végre egy egyszerű ((A || B) && C) a Bash-ban?


Készen állok csak kibontani és ugyanazokat a parancsokat több blokkban megismételni:

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 

Válasz

A bash szintaxisa nem C-szerű, még akkor is, ha egy kis részét C ihlette. Nem lehet egyszerűen megpróbálni C kódot írni, és elvárni, hogy működjön.

A shell fő célja a parancsok futtatása. Az open-zárójeles parancs [ egy parancs, amely egyetlen tesztet hajt végre¹. Akár test néven is megírhatja (a záró zárójel nélkül). A || és && operátorok shell operátorok, parancsokat kombinálnak, nem teszteket.

Tehát, amikor

[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ] 

ír, akkor a következő elemzés

[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ] 

ugyanaz, mint

test [ "$A" -eq "0" || test "$B" -ne "0" ] && test "$C" -eq "0" 

Figyelje meg a kiegyensúlyozatlan zárójeleket? Igen, ez nem jó. A zárójeles kísérletnek ugyanaz a problémája: hamis zárójelek.

A parancsok együttes csoportosításának szintaxisa zárójel. A zárójelek elemzésének módja teljes parancsot igényel előttük, ezért új vonallal vagy pontosvesszővel kell befejeznie a zárójelek belsejében található parancsot.

if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then … 

Ott msgstr “” “alternatív mód a dupla zárójelek használata. Az egyes zárójelekkel ellentétben a dupla zárójelek a héj speciális szintaxisa. Elhatárolják a feltételes kifejezéseket . A dupla zárójelben olyan zárójeleket és operátorokat használhat, mint a && és ||. Mivel a dupla zárójel héj szintaxisa, a héj tudja, hogy amikor ezek az operátorok zárójelben vannak, akkor a feltételes kifejezés szintaxisának részét képezik, nem pedig a szokásos shell parancs szintaxisának.

if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then … 

Ha az összes teszt numerikus, akkor van még egy módja, amely elhatárolja a műtani kifejezéseket . Az aritmetikai kifejezések egész számításokat végeznek, nagyon C-szerű szintaxissal.

if (((A == 0 || B != 0) && C == 0)); then … 

Megtalálhatja az bash zárójelemet alapozó hasznos.

[ használható sima sh-ben. A [[ és a (( a bash-ra (és a ksh-re és a zsh-re) vonatkoznak.

¹ Ez is kombináljon több tesztet logikai operátorokkal, de ez nehézkes használni, és finom buktatói vannak, ezért nem fogom megmagyarázni.

Megjegyzések

  • Köszönöm Giles. Ez érvényes a Bash 2-re a Bash 4-en keresztül? Szükségem van valamilyen enyhén hordozhatóságra, de Kusalananda megemlített néhány dolgot, amit nem csináltam, hordozhatóak (ez azt jelenti-e, amit csinálok > nem hordozható?). Itt enyhén a Bash 2-től a Bash 4-ig jelent.
  • @jww [[ … ]] hozzáadva a bash 2.02-ben. ((…)) hozzáadva a bash 2.0-hoz.
  • @Giles – köszönet. A Bash 2 valószínűleg a legtöbbre röhögő. Kormányzásunk és nem hajlandóságunk miatt elhagyni a régebbi platformokat. A Bash 2 és a GCC 3 megjelenik a Fedora 1 tesztelésünkön. Időnként elengedünk egy régebbi platformot, de ennek okainak kell lennie. Nem ' t iratkozzon fel az Apple, a Microsoft, a Mozilla stb. elhagyási programokra.
  • @jww Kérjük, vegye figyelembe, hogy a || és a változás [ -ről [[ és (( -re. Egyenlő elsőbbség a [ -ben (zárójelekkel ellenőrizheti az értékelés sorrendjét), de & & nagyobb prioritással rendelkezik [[ és ((, mint a || (mint a C-ben).
  • @Roland No, zárójelben [[ … ]] vagy $((…)) csak csoportosításra szolgálnak.

Válasz

Használja a [[ parancsot:

if [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]; then ... 

Ha a [ -t részesíti előnyben, akkor a következők működnek:

if [ \( "$A" -eq "0" -o "$B" -ne "0" \) -a "$C" -eq "0" ]; then ... 

Megjegyzések

  • Köszönöm, Stephen. Esetemben így használtam az első példáját … regex = ' ^ [0-9] + $ ' length = $ {#datearg} ha! [[$ datearg = ~ $ regex & & $ hossz -eq 8]]; akkor echo " hiba: A 8 " száma nem sok; fi

Válasz

Használja a -o operátort a beágyazott ||. Használhatja a -a alkalmazást a & & helyettesítésére is, ha más állításokban szükséges. .

 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 

Megjegyzések

  • Köszönöm. Találkoztam a -a és -o vel, de nem kísérleteztem velük. Valaki a Stack Overflow oldalán azt mondta, hogy kerülje el. Többnyire egyetértettem velük, mivel a szkript kevésbé olvasható használatukkal.
  • … de inkább hordozható.
  • @Kusalananda – Köszönjük a hordozhatósággal kapcsolatos fejfájást. A szkriptnek a Bash 2-től a Bash 4-ig tartó rendszereken kell futnia. [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]] problémákat okozhat velük kapcsolatban?
  • Nem lesznek problémák addig, amíg folytatja a bash vagy bármely más shell, amely megérti a [[ ... ]] szót.
  • Az -a használatának alsó oldala nem ' t rövidzárlat, ha az első kifejezés hamis. Tehát, ha rövidzárlatra támaszkodik, hogy megakadályozza a potenciálisan végzetes 2. kifejezés futását, akkor az -a nem használható. Példa: pastebin.com/zM77TXW1

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük