Käyttämällä lausetta $ (()), (())

Shell-komentosarjassa voimme korvata expr $a*$b $(($a+$b)).

Mutta miksi ei vain (($a+$b)), koska missä tahansa resurssissa on kirjoitettu, että (()) on tarkoitettu kokonaislukulaskennalle.

Käytämme siis $(()), kun muuttujia on kokonaislukuarvojen sijaan. Ja mitä meidän tulisi käyttää $(()) -tekstin sijaan, kun muuttujat voivat saada kelluvia arvoja?

Kommentit

Vastaus

  1. Aritmeettisessa muodossa expr on arkaainen. Älä käytä sitä. *

  2. $((...)) ja ((...)) ovat hyvin samankaltaisia. Molemmat tekevät vain kokonaislukulaskelmia. Erona on, että $((...)) palauttaa laskutoimituksen tuloksen ja ((...)) ei. Siten $((...)) on hyödyllinen lausekkeissa echo:

    $ a=2; b=3; echo $((a*b)) 6 

    ((...)) on hyödyllinen, kun haluat määrittää muuttujan tai asettaa poistumiskoodin:

    $ a=3; b=3; ((a==b)) && echo yes yes 
  3. Jos haluat kelluvan pistelaskutoimituksia, käytä bc tai awk:

    $ echo "4.7/3.14" | bc -l 1.49681528662420382165 $ awk "BEGIN{print 4.7/3.14}" 1.49682 

* Syrjäisenä expr pysyy hyödyllisenä merkkijonojen käsittelyssä, kun maapallot eivät ole riittävän hyvät ja POSIX-menetelmä tarvitaan säännöllisten lausekkeiden käsittelemiseksi.

Kommentit

  • Jos lauseke on arkaainen, mitä meidän tulisi käyttää lausekkeen sijasta: '. * '
  • Jos s on kuorimuuttuja, sen pituus on ${#s}
  • $ {#} tarkoittaa useita argumentteja ja $ (# s} tarkoittaa muuttujan merkkien määrää?
  • Kyllä. Se, että ' on oikein.
  • @Stranger Monet expr STRING : REGEX -käytännöt voidaan kirjoittaa nimellä case STRING in PATTERN). expr on hyödyllinen vain, jos REGEX-tiedostoa ei voida ' ilmaista kuorimerkkeillä.

Vastaa

lauseke on vanha, mutta sillä on vain yksi rajoitettu käyttö, jonka voin ajatella. Sano, että haluat hakea merkkijonoa. Jos haluat pysyä POSIXissa grepin kanssa, sinun on käytettävä putkea:

if echo november | grep nov then : do something fi 

expr voi tehdä tämän ilman putkea:

if expr november : nov then : do something fi 

ainoa saalis on, että expr toimii ankkuroitujen merkkijonojen kanssa, joten jos haluat sovittaa alkuun, sinun on muutettava REGEXP:

if expr november : ".*ber" then : do something fi 

Mitä tulee (( )) -sovellukseen, tämä rakenne ei ole POSIX , joten sitä tulisi välttää.

Mitä tulee $(( )) -sivustoon, sinun ei tarvitse sisällyttää dollarimerkkiä:

$ fo=1 $ go=2 $ echo $((fo + go)) 3 

kommentit

  • Monet expr STRING : REGEX -tyyppiset käyttötavat voidaan kirjoittaa nimellä case STRING in PATTERN). expr on hyödyllinen vain, jos REGEX-tiedostoa ei voida ' ilmaista kuorimerkkeillä.

Vastaa

Näyttää siltä, että seuraavat ohjelmat tekevät enemmän tai vähemmän samanlaisia ja ne eivät todellakaan eroa toisistaan. Mutta se ei ole totta.

#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=$((s+1)) echo $s 

Tämä on oikea tapa toteuttaa tämä. Kuori arvioi lausekkeen s + 1, joka voidaan määrittää muuttujalle.

#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=`expr $s+1` echo $s 

Tässä lauseke lasketaan expr-ohjelmalla, joka ei ole sisäänrakennettu shell, mutta ulkoinen Unix-ohjelma. Joten sen sijaan, että yksinkertaisesti lisätään 1 ja s, ohjelma on käynnistettävä ja sen lähtö on luettava ja kirjoitettava muuttujaan. Ohjelman käynnistäminen vaatii paljon resursseja ja paljon aikaa. Ja tämä ohjelma suoritetaan 1000000 kertaa. Joten ohjelma on paljon hitaampi kuin edellinen. Koodi kuitenkin toimii oikein.

#!/bin/bash -e s=-1000 for (( i=0; i<1000000; i++ )), do ((s=s+1)) echo $s 

Jos -e-lippua ei aseteta, ohjelma toimii myös oikein. Mutta jos -e asetetaan, kun s = -1 ja ((s = s + 1)) lasketaan. Lauseke s = s + 1 arvioi arvon 0 ja ((0)): n poistumiskoodi on> 0, jonka kuori tulkitsee virheeksi ja kuori poistuu ohjelmasta.

Syynä -e-lipun asettamiseen on, että se on yksinkertaisin tapa käsitellä virhettä: pysäytä, jos virhe sattuu.

Vastaa

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