expr
ei näytä pitävän suluista (käytetty matematiikassa operaattorin prioriteetin selvittämiseksi):
expr 3 * (2 + 1) bash: syntax error near unexpected token `("
Kuinka ilmaista operaattorin prioriteetti bashissa?
Vastaa
Toinen tapa käyttää let
bash sisäänrakennettua:
$ let a="3 * (2 + 1)" $ printf "%s\n" "$a" 9
Huomaa
Kuten @ Stéphane Chazelas huomautti , bash
-kohdassa sinun tulisi käyttää ((...))
-kohtaa aritmeettiseen kohtaan expr
tai let
luettavuus.
Siirrettävyydelle käytä $((...))
, kuten @Bernhard vastaus .
kommentit
Vastaus
Voit käyttää sen sijaan aritmeettista laajennusta.
echo "$(( 3 * ( 2 + 1 ) ))" 9
Minun mielestäni tämä näyttää hiukan mukavammalta kuin expr
.
Lähettäjä man bash
Aritmeettinen laajennus Aritmeettinen laajennus mahdollistaa aritmeettisen lausekkeen arvioinnin ja tuloksen korvaamisen. Aritmeettisen laajennuksen muoto on:
$((expression))
Lauseketta käsitellään ikään kuin se olisi lainausmerkkien sisällä, mutta sulkeissa olevaa kaksoislainausta ei käsitellä erikseen. Kaikki lausekkeen tunnukset läpikäyvät parametrien laajentamisen, merkkijonolaajennuksen, komentojen korvaamisen ja lainausten poistamisen. Aritmeettiset laajennukset voidaan sijoittaa sisäkkäin.
Arviointi suoritetaan alla ARITMEETTISEN ARVIOINNIN alla lueteltujen sääntöjen mukaisesti. Jos lauseke on virheellinen, bash tulostaa epäonnistuneen viestin eikä korvaamista tapahdu.
Kommentit
- Luettavuuden lisäksi se ei myöskään vaadi ’ haaroittamista ylimääräiseen prosessiin aritmeettisen tekemiseksi; Kuori itse käsittelee sen ’.
- Huomaa, että POSIX-kuorissa se ’ kuuluu sanaan jakaminen, joten ’ on hyvä tapa lainata sitä luetteloyhteyksissä.
- Kun yritän tätä bash-kuoressa, saan ’ Laiton muuttujan nimi. ”
Vastaa
Ei ole syytä käyttää expr
aritmeettiseen toimintaan nykyaikaisissa kuorissa.
POSIX määrittelee $((...))
Laajennusoperaattori. Voit siis käyttää sitä kaikissa POSIX-yhteensopivissa kuoreissa (kaikkien nykyisten Unix-tykkäysten, dash, bash, yash, mksh, zsh, posh, ksh sh
). ).
a=$(( 3 * (2 + 1) )) a=$((3*(2+1)))
ksh
esitteli myös sisäänrakennetun let
on läpäissyt samanlaisen aritmeettisen lausekkeen, ei laajene mihinkään, mutta palauttaa poistumistilan sen perusteella, onko lauseke resolv es 0: een tai ei, kuten expr
:
if let "a = 3 * (2 + 1)"; then echo "$a is non-zero" fi
Koska lainaus tekee siitä hankalan eikä hyvin luettavissa (ei tietyssä määrin kuin expr
tietysti), ksh
esitteli myös ((...))
vaihtoehtoinen muoto:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then echo "$a is non-zero and 3 > 1" fi ((a+=2))
joka on paljon luettavampi ja jota tulisi käyttää sen sijaan.
let
ja ((...))
ovat käytettävissä vain ksh
, zsh
ja bash
.$((...))
-syntaksia tulisi suositella, jos siirrettävyys muihin kuoreihin tarvitaan, expr
tarvitaan vain pre-POSIX Bourne-tyyppisille kuoreille (yleensä Bourne-kuori tai Almquist-kuoren varhaiset versiot).
Ei-Bourne-rintamalla on muutama kuori, joissa on sisäänrakennettu aritmeettinen operaattori:
-
csh
/tcsh
(oikeastaan ensimmäinen Unix-kuori, johon on sisäänrakennettu aritmeettinen arviointi):@ a = 3 * (2 + 1)
-
akanga
(perustuurc
)a = $:"3 * (2 + 1)"
-
historian muistiinpanona Almquist-kuoren alkuperäisellä versiolla, joka julkaistiin Usenetissä vuonna 1989, oli
expr
sisäänrakennettu (tosiasiallisesti yhdistettytest
: iin), mutta se poistettiin myöhemmin.
Kommentit
- Opin sinulta joka päivä jotain uutta, St é phane. Arvostan suuresti POSIX-komentotulkkiasi!
- Entä
: $((a = a*2))
? - Entä jos minulla on liukuluku? Lausekkeeni on a = $ ((-14 + 0,2 * (1 + 2 + 3))). Virhetunnus on ” .2 * (1 + 2 + 3) ”
- @Blaise, sitten sinä ’ d tarvitsee kuoren, joka tukee kelluvia kohtia
$((...))
, kuten zsh, ksh93 tai yash.
Vastaus
expr
on ulkoinen komento, se ei ole erityinen kuoren syntakse. Siksi, jos haluat expr
nähdäksesi kuoren erikoismerkit, sinun on suojattava niitä kuoren jäsentämiseltä lainaamalla niitä. Lisäksi expr
edellyttää, että jokainen numero ja operaattori välitetään erillisenä parametrina. Siten:
expr 3 \* \( 2 + 1 \)
Ellei työskentele antiikkisen unix-järjestelmän parissa 1970- tai 1980-luvuilla, ei ole juurikaan syytä käyttää expr
. Vanhoina aikoina kuoreilla ei ollut sisäänrakennettua tapaa suorittaa laskutoimitusta, ja sinun oli sen sijaan soitettava expr
-apuohjelmaan. Kaikissa POSIX-kuoreissa on sisäänrakennettu aritmeettinen aritmeettisen laajennuksen syntaksin kautta.
echo "$((3 * (2 + 1)))"
konstrukti $((…))
laajenee aritmeettisen lausekkeen tulokseen (kirjoitettu desimaalilla). Bash, kuten useimmat komentotulkit, tukee vain kokonaislukuaritmeettista modulo 2 64 (tai modulo 2 32 vanhemmille bash-versioille ja joillekin muille 32-bittisten koneiden kuorille).
Bash tarjoaa mukavuussyntaksin , kun haluat suorittaa tehtäviä tai testata, onko lauseke 0, mutta älä välitä tuloksesta. Tämä rakenne on myös ksh: ssä ja zsh: ssä, mutta ei tavallisessa sh: ssä.
((x = 3 * (2+1))) echo "$x" if ((x > 3)); then …
Lukuaritmeettisen lisäksi expr
tarjoaa muutaman merkkijonon manipulointitoiminnon. Nämäkin ovat POSIX-kuorien ominaisuuksien alaisia, lukuun ottamatta yhtä: expr STRING : REGEXP
testaa, vastaako merkkijono määritettyä regexp-arvoa. POSIX-kuori ei voi tehdä tätä ilman ulkoisia työkaluja, mutta bash voi käyttää [[ STRING =~ REGEXP ]]
( erilaisella regexp-syntaksilla – expr
on klassinen työkalu, joka käyttää BRE: tä, bash käyttää ERE: tä).
Ellet skriptejä korjaa uudelleen jotka toimivat 20-vuotiailla järjestelmillä, sinun ei tarvitse tietää, että expr
on koskaan ollut olemassa. Käytä kuoriaritmeettista.
Kommentit
-
expr foo : '\(.\)'
myös purkaa tekstiä.bash
’ sBASH_REMATCH
saavuttaa jotain vastaavaa. Se tekee myös merkkijonojen vertailua, jota POSIX[
ei tee (vaikka voisi kuvitella tapoja käyttääsort
siihen). - alleviivaus syntaksin paikkamerkkinä — sinä Schemer, @Giles? :]
- @RubyTuesdayDONO En käyttänyt ’ t alleviivaa tässä. Luetko väärin U + 2026 HORIZONTAL ELLIPSIS -ohjelmaa? Jos näin on, kokeile käyttää isompaa kirjasinta.
- @Giles – okei, kyllä, se näyttää vain alaviivalta kirjasinkoon takia. minulle ” Schemer ” on täydennysosa, ja se ’ ei pidä ellipsistä versus alleviiva muuttaa merkitystä joka tapauksessa … ei tarvitse olla harmaantunut sen suhteen: /
Vastaa
Käytä sulkeita lainaukset:
expr 3 "*" "(" 2 "+" 1 ")" 9
Lainausmerkit estävät bashia tulkitsemasta sulkeita bash-syntaksina.
Kommentit
- Nicolas kuvaa, mutta ei selitä, että komentorivillä
expr
olevat tunnukset on erotettava välilyönneillä; niin; esimerkiksiexpr 3 "*" "(2" "+" "1)"
ei toimi . (BTW: n lisäksi sinun ei todennäköisesti tarvitse lainata+
-merkkiä.) - Suluissa ei ole ’ t avainsanoja, kuten
while
ja[[
, ne ’ syntaksi uudelleen. Jos ne olisivat avainsanoja, niitä ei tulkita ’ sellaisiksi komentoargumenteissa. Tarvitset lainausmerkkejä, jotta bash ei jäsennä niitä ’ t, vaan näkee merkkijonon kirjaimen.
Vastaa
Jos sinulla on bc ..
echo "3 * (2 + 1)"|bc 9
let
. Se ’ ei ole enää vakio tai kannettava kuin(( a = 3 * (2 + 1) ))
(molemmat tulevatksh
ja ovat saatavana vain tiedostoina ksh, bash ja zsh), ja se on ’ vähemmän luettavissa tai helppo lainata. Käytä kannettavaaa=$((3 * (2 + 1)))
.((a = 3 * (2 + 1) ))
, yksi siirrettävyyden kannaltaa=$((3 * (2 + 1)))
), joten se ’ ei ole huomautus sinua tai vastaustasi vastaan, mutta sitä vastaan, että se on valittu vastaus ja paras maalintekijä .a=1 $[a+2]
taia=1 b=2 $[a+b]
. Onko heidän syytä välttää tätä syntaksia?