Ved hjelp av expr, $ (()), (())

I shell-skript kan vi erstatte expr $a*$b med $(($a+$b)).

Men hvorfor ikke bare med (($a+$b)), for i en hvilken som helst ressurs står det at (()) er for heltallsberegning.

Så vi bruker $(()) når det er variabler i stedet for heltalsverdier, gjør vi? Og hva skal vi bruke i stedet for $(()) når variabler kan motta flyteverdier?

Kommentarer

Svar

  1. For regning er expr arkaisk. Ikke bruk den. *

  2. $((...)) og ((...)) er veldig like. Begge gjør bare heltallberegninger. Forskjellen er at $((...)) returnerer resultatet av beregningen og ((...)) ikke. Dermed $((...)) er nyttig i echo utsagn:

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

    ((...)) er nyttig når du vil tilordne en variabel eller angi en utgangskode:

    $ a=3; b=3; ((a==b)) && echo yes yes 
  3. Hvis du vil flyte punktberegninger, bruk bc eller awk:

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

* Som en side, forblir expr nyttig for strenghåndtering når globs ikke er gode nok og en POSIX-metode er nødvendig for å håndtere vanlige uttrykk.

Kommentarer

  • Hvis expr er arkaisk, hva skal vi bruke i stedet for expr text: '. * '
  • Hvis s er en skallvariabel, er dens lengde ${#s}
  • $ {#} betyr et antall argumenter og $ (# s} betyr at antall tegn i en variabel gjør det?
  • Ja. At ' er riktig.
  • @Stranger Mange bruksområder for expr STRING : REGEX kan skrives som case STRING in PATTERN). expr er bare nyttig når REGEX kan ' t uttrykkes med jokertegn fra skall.

Svar

expr er gammel, men det har en begrenset bruk jeg kan tenke meg. Si at du vil søke i en streng. Hvis du vil være POSIX med grep, må du bruke et rør:

if echo november | grep nov then : do something fi 

expr kan gjøre dette uten et rør:

if expr november : nov then : do something fi 

den eneste fangsten er ekspr fungerer med forankrede strenger, så hvis du vil matche etter begynnelsen, må du endre REGEXP:

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

Når det gjelder (( )), er denne konstruksjonen ikke POSIX , så det bør unngås.

Når det gjelder $(( )), trenger du ikke å ta med dollartegnet:

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

Kommentarer

  • Mange bruksområder av expr STRING : REGEX kan skrives som case STRING in PATTERN). expr er bare nyttig når REGEX kan ' t uttrykkes med jokertegn fra skall.

Svar

Det ser ut til at følgende programmer gjør mer eller mindre det samme, og de skiller seg ikke veldig ut. Men det er ikke sant.

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

Dette er den riktige måten å implementere dette på. Uttrykket s + 1 blir evaluert av skallet og kan tilordnes en variabel.

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

Her vil uttrykket bli beregnet av programmet expr, som ikke er et shell-innebygd men et eksternt Unix-program. Så i stedet for å bare legge til 1 og s, må et program startes og utgangen må leses og skrives til variabelen. Å starte et program trenger mye ressurser og mye tid. Og dette programmet kjøres 1000000 ganger. Så programmet vil være mye tregere enn det forrige. Likevel fungerer koden riktig.

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

Hvis -e-flagget ikke er angitt, vil programmet også fungere riktig. Men hvis -e er satt når s = -1 og ((s = s + 1)) beregnes. Uttrykket s = s + 1 evalueres til 0 og utgangskoden til ((0)) er> 0 som tolkes som en feil av skallet og skallet går ut av programmet.

Årsaken til å sette flagget -e er at det er den enkleste måten å behandle feil på: stopp hvis en feil oppstår.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *