Useita loogisia operaattoreita, ((A || B) & & C) ja “ syntaksivirhe odottamattoman tunnuksen lähellä ”

Minä työskentelen Bash 3: n kanssa ja yritän muodostavat ehdollisen. C / C ++: ssa sen kuollut yksinkertainen: ((A || B) && C). Bashissa se ei osoittautunut niin (mielestäni Git-kirjoittajien on täytynyt antaa tämä koodi ennen kuin he siirtyivät muihin pyrkimyksiin).

Tämä ei toimi. Huomaa, että <0 or 1> ei ole merkkijonon kirjain; se tarkoittaa 0 tai 1 (yleensä tulee 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 

Tuloksena on

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

Yritin sitten:

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

tuloksena on:

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

Osa ongelmasta on, että hakutulokset ovat triviaalisia esimerkkejä eivätkä monimutkaisempia esimerkkejä yhdistetyillä ehdollisilla.

Kuinka suoritan yksinkertaisen ((A || B) && C) Bashissa?


Olen valmis vain avaamaan sen ja toistamaan samat komennot useissa lohkoissa:

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 

Vastaus

Bashin syntaksit eivät ole C: n kaltaisia, vaikka pieni osa siitä olisi C: n innoittama. Et voi yksinkertaisesti yrittää kirjoittaa C-koodia ja odottaa sen toimivan.

Kuoren pääkohde on komentojen suorittaminen. Open-bracket-komento [ on komento, joka suorittaa yhden testin¹. Voit jopa kirjoittaa sen nimellä test (ilman viimeistä sulkeutta). || – ja && -operaattorit ovat kuorioperaattoreita, ne yhdistävät komentoja eivätkä testejä.

Joten kirjoittaessasi

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

se on jäsennelty nimellä

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

mikä on sama kuin

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

Huomaa epäsymmetriset sulkeet? Joo, se ei ole hyvä. Sulkuyritykselläsi on sama ongelma: väärät hakasulkeet.

Kommenttien ryhmittelemisen syntaksi on aaltosulkeja. Aaltosulkujen jäsentäminen vaatii täydellisen komennon ennen niitä, joten sinun on lopetettava komento aaltosulkeissa uudella rivillä tai puolipisteellä.

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

Siellä ”vaihtoehtoinen tapa käyttää kaksoissulkeita. Toisin kuin yksittäiset suluissa, kaksoissulkeet ovat erityisiä kuoren syntaksia. Ne rajaavat ehdolliset lausekkeet . Tuplasulkeiden sisällä voit käyttää sulkeita ja operaattoreita, kuten && ja ||. Koska kaksoissulkeet ovat kuoren syntaksia, kuori tietää, että kun nämä operaattorit ovat suluissa, ne ovat osa ehdollisen lausekkeen syntaksia, eivät osa tavallista komentokomennon syntaksia.

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

Jos kaikki testisi ovat numeerisia, on olemassa toinenkin tapa, joka rajaa artehmeettiset lausekkeet . Aritmeettiset lausekkeet suorittavat kokonaislukulaskennat hyvin C-tyyppisellä syntaksilla.

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

Löydät bash-haarukan pohjamaali hyödyllinen.

[ voidaan käyttää tavallisessa muodossa. [[ ja (( ovat ominaisia bashille (ja ksh: lle ja zsh: lle).

¹ Se voi myös Yhdistä useita testejä loogisten operaattoreiden kanssa, mutta tämä on hankala käyttää ja sillä on hienovaraisia sudenkuoppia, joten en selitä sitä.

Kommentit

  • Kiitos Giles. Pitääkö tämä paikkansa Bash 2: n ja Bash 4: n välillä? Tarvitsen jotain lievästi siirrettävää, mutta Kusalananda mainitsi, että joitain asioita, joita en en tee, ovat kannettavia (tarkoittako tämä sitä, että minä teen > ei kannettava?). Tässä lievästi tarkoittaa Bash 2: sta Bash 4: ään.
  • @jww [[ … ]] lisättiin bashissa 2.02. ((…)) lisättiin bash 2.0: een.
  • @Giles – kiitos. Bash 2 on todennäköisesti naurettava useimmille. Se johtuu hallinnostamme ja haluttomuudesta. hylätä vanhemmat alustat. Bash 2 ja GCC 3 näkyvät Fedora 1 -testissä. Annamme vanhemman alustan mennä ajoittain, mutta siihen on oltava syitä. Emme ' t tilaa Applen, Microsoftin, Mozillan jne. hylkäysohjelmat.
  • @jww Ymmärrä, että || ja vaihda arvosta [ arvoon [[ ja ((. Yhtäläinen etusija [ -ohjelmassa (käytä sulkeita ohjaamaan arvioinnin järjestystä), mutta & & on suurempi etusija [[: ssä ja (( kuin || (kuten kohdassa C).
  • @Roland No, suluissa [[ … ]] tai $((…)) ovat vain ryhmittelyä varten.

vastaus

Käytä [[:

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

Jos haluat [, seuraavat toimet toimivat:

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

Kommentit

  • Kiitos, Stephen. Minun tapauksessani käytin ensimmäistä esimerkkiäsi näin … regex = ' ^ [0-9] + $ ' length = $ {#datearg} jos! [[$ datearg = ~ $ regex & & $ pituus -eq 8]]; sitten echo " -virhe: Ei lukumäärää 8 "; fi

Vastaa

Käytä -o -operaattoria sisäkkäin ||. Voit myös käyttää -a -merkkiä korvaamaan & &, jos tarpeen muissa lausunnoissa. .

 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 

Kommentit

  • Kiitos. Löysin -a ja -o, mutta en kokeillut niitä. Joku Stack Overflow -sivustolla sanoi välttävän sitä. Olen enimmäkseen samaa mieltä heidän kanssaan, koska käsikirjoitus on vähemmän luettavissa niiden avulla.
  • … mutta siirrettävämpi.
  • @Kusalananda – Kiitos siirrettävyydestä. Komentosarjan on suoritettava järjestelmissä, joissa on Bash 2 – Bash 4. Onko [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]] heillä ongelmia?
  • Ei ongelmia ole niin kauan kuin jatkat bash tai mikä tahansa muu kuori, joka ymmärtää [[ ... ]].
  • -Käytön alaosa on se, että se ei ' t oikosulku, jos ensimmäinen lauseke on väärä. Joten jos luotat oikosulkuun estämään mahdollisen kohtalokkaan toisen lausekkeen suorittamisen, et voi käyttää -a. Esimerkki: pastebin.com/zM77TXW1

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *