Folosind expr, $ (()), (())

În scriptul shell putem înlocui expr $a*$b $(($a+$b)).

Dar de ce nu doar cu (($a+$b)), deoarece în orice resursă este scris că (()) este pentru calculul întreg.

Deci, folosim $(()) atunci când există variabile în loc de valori întregi, nu? Și ce ar trebui să folosim în loc de $(()) atunci când variabilele pot primi valori float?

Comentarii

Răspuns

  1. Pentru aritmetică, expr este arhaic. Nu-l utilizați. *

  2. $((...)) și ((...)) sunt foarte asemănătoare. Ambele fac numai calcule întregi. Diferența este că $((...)) returnează rezultatul calculului și ((...)) nu. Astfel $((...)) este util în declarațiile echo:

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

    ((...)) este util atunci când doriți să atribuiți o variabilă sau să setați un cod de ieșire:

    $ a=3; b=3; ((a==b)) && echo yes yes 
  3. Dacă doriți să flotați calcule punctuale, utilizați bc sau awk:

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

* Ca o parte, expr rămâne util pentru manipularea șirurilor atunci când globurile nu sunt suficient de bune și este necesară o metodă POSIX pentru a gestiona expresiile regulate.

Comentarii

  • Dacă expr este arhaic ce ar trebui să folosim în loc de text expr: '. * '
  • Dacă s este o variabilă shell, lungimea sa este ${#s}
  • $ {#} înseamnă un număr de argumente, iar $ (# s} înseamnă un număr de caractere ale unei variabile, nu?
  • Da. Acel drept ' este corect.
  • @Stranger Multe utilizări ale expr STRING : REGEX pot fi scrise ca case STRING in PATTERN). expr este util numai atunci când REGEX nu poate ' să fie exprimat cu metacaractere shell.

Răspuns

expr este vechi, dar are o utilizare limitată la care mă pot gândi. Spuneți că doriți să căutați un șir. Dacă doriți să rămâneți POSIX cu grep, trebuie să utilizați o conductă:

if echo november | grep nov then : do something fi 

expr poate face acest lucru fără o conductă:

if expr november : nov then : do something fi 

singura captură este că expr funcționează cu șiruri ancorate, deci, dacă doriți să se potrivească după început, trebuie să modificați REGEXP:

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

În ceea ce privește (( )), acest construct nu este POSIX , deci ar trebui evitat.

În ceea ce privește $(( )), nu trebuie să includeți semnul dolar:

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

Comentarii

  • Multe utilizări ale expr STRING : REGEX pot fi scrise ca case STRING in PATTERN). expr este util numai atunci când REGEX nu poate ' să fie exprimat cu metacaractere shell.

Răspuns

Se pare că următoarele programe fac mai mult sau mai puțin la fel și nu diferă cu adevărat. Dar acest lucru nu este adevărat.

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

Acesta este modul corect de implementare. Expresia s + 1 este evaluată de shell și poate fi atribuită unei variabile.

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

Aici expresia va fi calculată de programul expr, care nu este un shell integrat, ci un program extern Unix. Deci, în loc să adăugați pur și simplu 1 și s, un program trebuie pornit și rezultatul acestuia trebuie citit și scris în variabilă. Începerea unui program are nevoie de multe resurse și mult timp. Și acest program este rulat de 1000000 de ori. Deci programul va fi mult mai lent decât precedentul. Cu toate acestea, codul funcționează corect.

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

Dacă steagul -e nu este setat, programul va funcționa și el. Dar dacă -e este setat când s = -1 și ((s = s + 1)) este calculat. Expresia s = s + 1 se evaluează la 0, iar codul de ieșire al ((0)) este> 0, care este interpretat ca o eroare de către shell și shell-ul iese din program.

Motivul pentru a seta semnalizatorul -e este că este cel mai simplu mod de procesare a erorilor: opriți-vă dacă apare o eroare.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *