Ve skriptu prostředí můžeme nahradit expr $a*$b
$(($a+$b))
.
Ale proč ne nejen s (($a+$b))
, protože v každém zdroji je napsáno, že (())
je pro celočíselný výpočet.
Takže $(())
používáme, když místo celočíselných hodnot existují proměnné, že? A co bychom měli použít místo $(())
, když proměnné mohou přijímat plovoucí hodnoty?
Komentáře
- Zobrazit také unix.stackexchange.com/questions/149823/…
Odpověď
-
Pro aritmetiku je
expr
archaický. Nepoužívejte to. * -
$((...))
a((...))
jsou si velmi podobné. Oba provádějí pouze celočíselné výpočty. Rozdíl je v tom, že$((...))
vrací výsledek výpočtu a((...))
nikoli. Tedy$((...))
je užitečný veecho
prohlášeních:$ a=2; b=3; echo $((a*b)) 6
((...))
je užitečné, když chcete přiřadit proměnnou nebo nastavit výstupní kód:$ a=3; b=3; ((a==b)) && echo yes yes
-
Pokud chcete plovoucí bodové výpočty, použijte
bc
neboawk
:$ echo "4.7/3.14" | bc -l 1.49681528662420382165 $ awk "BEGIN{print 4.7/3.14}" 1.49682
* Kromě toho expr
zůstává užitečný pro zpracování řetězců, když globy nejsou dost dobré a pro zpracování regulárních výrazů je nutná metoda POSIX.
Komentáře
- Pokud je expr archaický, co bychom měli použít místo expr textu: '. * '
- Pokud je
s
proměnná prostředí, její délka je${#s}
- $ {#} znamená počet argumentů a $ (# s} znamená počet znaků proměnné, že?
- Ano. To ' má pravdu.
- @Stranger Mnoho použití
expr STRING : REGEX
lze napsat jakocase STRING in PATTERN)
.expr
je užitečný, pouze pokud REGEX nelze ' vyjádřit zástupnými znaky prostředí.
Odpověď
expr je starý, ale má jedno omezené použití, na které si myslím. Řekněme, že chcete vyhledat řetězec. Pokud chcete zůstat POSIX s grep, musíte použít rouru:
if echo november | grep nov then : do something fi
expr to dokáže bez roury:
if expr november : nov then : do something fi
jediným úlovkem je expr pracuje s ukotvenými řetězci, takže pokud se chcete shodovat po začátku, musíte změnit REGEXP:
if expr november : ".*ber" then : do something fi
Pokud jde o (( ))
, tento konstrukt není POSIX , takže je třeba se mu vyhnout.
Pokud jde o $(( ))
, nemusíte uvádět znak dolaru:
$ fo=1 $ go=2 $ echo $((fo + go)) 3
Komentáře
- Mnoho použití
expr STRING : REGEX
lze zapsat jakocase STRING in PATTERN)
.expr
je užitečný, pouze pokud REGEX nelze ' vyjádřit zástupnými znaky prostředí.
Odpověď
Zdá se, že následující programy jsou víceméně stejné a ve skutečnosti se neliší. Ale to není pravda.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=$((s+1)) echo $s
Toto je správný způsob implementace. Výraz s + 1 je vyhodnocen shellem a lze jej přiřadit k proměnné.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=`expr $s+1` echo $s
Zde bude výraz vypočítán programem expr, který není zabudován do shellu, ale je externím unixovým programem. Takže místo jednoduchého přidání 1 a s musí být spuštěn program a jeho výstup musí být přečten a zapsán do proměnné. Spuštění programu vyžaduje spoustu zdrojů a spoustu času. A tento program je spuštěn 10 000 000krát. Program tedy bude mnohem pomalejší než předchozí. Kód přesto funguje správně.
#!/bin/bash -e s=-1000 for (( i=0; i<1000000; i++ )), do ((s=s+1)) echo $s
Pokud není nastaven příznak -e, bude program fungovat také správně. Pokud je však -e nastaveno, když s = -1 a ((s = s + 1)). Vypočítá se výraz s = s + 1 na hodnotu 0 a kód ukončení ((0)) je> 0, což shell interpretuje jako chybu a shell ukončí program.
Důvodem pro nastavení parametru -e je, že se jedná o nejjednodušší způsob zpracování chyb: zastavit, pokud dojde k chybě.