Aritmetická expanze
Výraz
$(( term ))
se expanduje na výsledek vyhodnocení aritmetického výrazu term. Na rozdíl od
expr a od tvaru $[ … ] použitého v kapitole Aritmetika
jde o vestavěnou konstrukci, která nespouští žádný další proces. Tvar
$(( … )) je dnes doporučovaný; $[ … ] je zastaralý a v nových skriptech se
mu vyhýbáme,1 i když jej ve starším kódu potkáme. Uvnitř výrazu jsou povoleny mezery.
> echo $(( 2 + 3 ))
5
> echo $(( 10 / 3 ))
3
> echo $(( 10 % 3 ))
1
Proměnné uvnitř
Uvnitř $(( )) se na jména proměnných dívá shell jako na proměnné i bez $.
Obě následující varianty jsou tedy správné, druhá je čitelnější.
var1=10
var2=20
vysledek=$(( ${var1} * ${var2} ))
vysledek=$(( var1 * var2 ))
Prázdná nebo nenastavená proměnná se vyhodnotí jako 0. To je pohodlné, ale snadno to zamaskuje překlep ve jméně proměnné.
> echo $(( NEEXISTUJE + 5 ))
5
Operátory
K dispozici jsou operátory známé z jazyka C, včetně priority a závorek:
- aritmetické
+ - * / % **(mocnina) - porovnání
< <= > >= == != - logické
&& || ! - bitové
& | ^ ~ << >> - přiřazovací
= += -= *= /= %= - inkrement a dekrement
++ -- - ternární operátor
podmínka ? a : b
> echo $(( 2 ** 10 ))
1024
> echo $(( 1 << 8 ))
256
> x=5
> echo $(( x > 3 ? 100 : 200 ))
100
Porovnání vrací 1 pro pravdu a 0 pro nepravdu. Pozor, je to opačně než u návratových hodnot příkazů (viz Návratové hodnoty).
Aritmetika jako příkaz
Kromě expanze existuje i tvar (( term )), který je příkazem. Výraz se
vyhodnotí a příkaz skončí s návratovou hodnotou 0, je-li výsledek nenulový,
a s hodnotou 1, je-li výsledek nula. To je právě obrácení zmíněné výše, které
umožňuje psát podmínky přirozeně.
if (( pocet > 10 ))
then
echo "vice nez deset"
fi
# pocitadlo v cyklu
i=0
while (( i < 5 ))
do
echo ${i}
(( i++ ))
done
Ve srovnání s [ "${a}" -gt "${b}" ] je tento zápis čitelnější a nemusíme
řešit uvozovky, protože uvnitř (( )) neprobíhá dělení slov. Jde ovšem
o rozšíření Bashe, které v jiných shellech nemusí být k dispozici (viz
Větvení).
Konstrukce (( )) se objevuje také v hlavičce céčkového cyklu for, který jsme
viděli v kapitole Cykly:
for (( i=1; i <= 10; i++ ))
do
echo ${i}
done
Číselné soustavy
Číslo začínající nulou je považováno za osmičkové, číslo začínající 0x za
šestnáctkové. Obecně lze soustavu zapsat jako zaklad#cislo.
> echo $(( 010 ))
8
> echo $(( 0xff ))
255
> echo $(( 2#1010 ))
10
Osmičková interpretace je zdrojem chyb při práci s daty, která používají nuly zleva — třeba s měsíci nebo dny v datu.
> MESIC=09
> echo $(( MESIC + 1 ))
bash: 09: value too great for base (error token is "09")
Řešením je vynutit desítkovou soustavu zápisem 10#:
> echo $(( 10#${MESIC} + 1 ))
10
Aritmetika je celočíselná
Stejně jako u expr platí, že $(( )) počítá pouze s celými čísly a dělení
ořezává. Pro výpočty s desetinnými čísly je nutné použít bc, jak je popsáno
v kapitole Aritmetika.
-
$[ … ]je v dokumentaci Bashe uveden jako zastaralý a v budoucích verzích může zmizet. V ukázkách ve zbytku textu se ještě vyskytuje. ↩