Ved hjælp af expr, $ (()), (())

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

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

Så vi bruger $(()) når der er variabler i stedet for heltal værdier gør vi? Og hvad skal vi bruge i stedet for $(()) når variabler kan modtage float-værdier?

Kommentarer

Svar

  1. For aritmetik er expr arkaisk. Brug det ikke. *

  2. $((...)) og ((...)) er meget ens. Begge foretager kun heltalberegninger. Forskellen er, at $((...)) returnerer resultatet af beregningen, og ((...)) ikke. Således $((...)) er nyttigt i echo udsagn:

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

    ((...)) er nyttigt, når du vil tildele en variabel eller indstille en udgangskode:

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

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

* Som en sidebemærkning forbliver expr nyttig til strenghåndtering, når globs ikke er gode nok, og en POSIX-metode er nødvendig for at håndtere regulære udtryk.

Kommentarer

  • Hvis expr er arkaisk, hvad skal vi bruge i stedet for expr-tekst: '. * '
  • Hvis s er en skalvariabel, er dens længde ${#s}
  • $ {#} betyder et antal argumenter, og $ (# s} betyder, at et antal tegn i en variabel gør det?
  • Ja. At ' er rigtigt.
  • @Stranger Mange anvendelser af expr STRING : REGEX kan skrives som case STRING in PATTERN). expr er kun nyttigt, når REGEX kan ' t udtrykkes med shell-jokertegn.

Svar

expr er gammel, men det har en begrænset anvendelse, jeg kan tænke på. Sig, at du vil søge i en streng. Hvis du vil forblive POSIX med grep, skal du bruge et rør:

if echo november | grep nov then : do something fi 

expr kan gøre dette uden et rør:

if expr november : nov then : do something fi 

den eneste fangst er expr fungerer med forankrede strenge, så hvis du vil matche efter starten, skal du ændre REGEXP:

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

Med hensyn til (( )) er denne konstruktion ikke POSIX , så det bør undgås.

Med hensyn til $(( )) behøver du ikke medtage dollartegnet:

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

Kommentarer

  • Mange anvendelser af expr STRING : REGEX kan skrives som case STRING in PATTERN). expr er kun nyttigt, når REGEX kan ' t udtrykkes med shell-jokertegn.

Svar

Det ser ud til, at de følgende programmer gør mere eller mindre det samme, og de adskiller sig ikke rigtig. Men det er ikke sandt.

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

Dette er den rigtige måde at implementere dette på. Udtrykket s + 1 evalueres af skallen og kan tildeles en variabel.

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

Her beregnes udtrykket af programmet expr, som ikke er en shell-indbygget men et eksternt Unix-program. Så i stedet for blot at tilføje 1 og s, skal et program startes, og dets output skal læses og skrives til variablen. At starte et program har brug for mange ressourcer og meget tid. Og dette program køres 1000000 gange. Så programmet vil være meget langsommere end det foregående. Ikke desto mindre fungerer koden korrekt.

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

Hvis -e-flag ikke er indstillet, fungerer programmet også korrekt. Men hvis -e er indstillet når s = -1 og ((s = s + 1)) beregnes. Udtrykket s = s + 1 evalueres til 0, og udgangskoden for ((0)) er> 0, som fortolkes som en fejl af skallen og skallen forlader programmet.

Årsagen til at indstille flaget -e er, at det er den enkleste måde at behandle fejl på: stop, hvis der opstår en fejl.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *