LX-SCR-INFO-rekenen
updated 7/27/10 00:09
rekenen
In alle vorige hoofdstukken hebben we leren lezen en schrijven, sorteren, beslissen, repetitieve handelingen verrichten, zelfs orde en netheid hebben we geleerd. Aan rekenen zijn we echter nog niet toegekomen. We hebben dit item bewust tot het laatst gehouden.
Bash scripting is nu eenmaal geen rekenmachine zoals fortran, maar gewoon een uitbreiding van de command line interface. Bash is bijzonder geschikt voor systeembeheer, veel meer dan om het even welke programmeertaal, veel meer dan C en JAVA die universeel heten te zijn.
Toch moeten we af en toe rekenen, al was het maar een teller aanpassen, of de grootte van een schijf omzetten naar leesbare karakters.
We moeten ook getallen met elkaar kunnen vergelijken, om zo beslissingen te kunnen nemen in een if, een while of een case. Bovendien nemen we hier ook even de tijd om te kijken hoe je voorwaarden kunt ANDen of ORren.
Maar eerst nog dit:
BASH rekent standaard alleen
met INTEGERS
En ten tweede: er zijn veel manieren om hetzelfde te doen
- $(( )) of $[ ]
deze syntax heeft geen probleem met spaties of dollartekens
$ z=4
$ z=$(( z+4 ))
$ echo $z
8
zoals reeds gezegd: alleen operaties met gehele getallen zijn toegelaten:
$ z=$(( z+3.5 ))
bash: z+3.5 : syntax error: invalid arithmetic operator (error token is ".5 ")
$ z=$(( z+5 ))
$ echo $z
17
$ z=$(( z-9 ))
$ echo $z
8
$ z=$(( z/3 ))
$ echo $z
2
je kan de dubbele (( ))
vervangen door [ ]
$ z=$[ z+5 ]
$ echo $z
10
$ z=$[z+5]
$ echo $z
15
|
$ a=3
$ b=8
$ c=4
$ z=$(( $a + $b - $c ))
$ echo $z
7
$ z=$(( $a+$b-$c ))
$ echo $z
7
$ z=$(($a+$b-$c))
$ echo $z
7
$ z=$((a+b-c))
$ echo $z
7
|
verkorte notering - pas op: werkt niet met [ ]:
$ a=30
$ (( a++ ))
$ echo $a
31
- let
let aanvaardt geen enkele spatie, dollartekens moeten op de juiste plaats
$ let a=12
$ echo $a
12
$ let a=12-12
$ echo $a
0
$ let a=12/2
$ echo $a
6
|
$ a=5
$ b=8
$ c=17
$ let a=$c/$a
$ echo $a
3
$ let a=$c+$b
$ echo $a
25
|
verkorte noteringen:
|
|
$ let a++
$ echo $a
26
|
$ let a+=1
$ echo $a
27
|
- Bewerkingen
bewerking
|
operator
|
gebruik (( ))
|
gebruik met let
|
optelling
|
+
|
$((4 + 5))
|
let x=4+5
|
aftrekking
|
-
|
$[ 7 - 7 ]
|
let x=7-7
|
vermenigvuldiging
|
*
|
$((3 * 2))
|
let x=3*2
|
deling
|
/
|
$((6 / 3))
|
let x=6/3
|
modulo (rest)
|
%
|
$((8 % 7))
|
let x=8%7
|
machtsverheffing
|
**
|
$[ 2 ** 8 ]
|
let x=2**8
|
- Bewerkingen met gelijkheidsteken
operator
|
bewerking met toewijzing
|
gebruik |
betekenis
|
= |
toewijzing
|
a=b |
a=b |
*= |
vermenigvuldiging
|
a*=b |
a=(a*b) |
/= |
deling
|
a/=b |
a=(a/b) |
%= |
modulo (rest)
|
a%=b |
a=(a%b) |
+= |
optelling
|
a+=b |
a=(a+b) |
-= |
aftrekking
|
a-=b |
a=(a-b) |
<<= |
Bit-shift naar links |
a<<=b |
a=(a<<b) |
>>= |
Bit-shift naar rechts |
a>>=b |
a=(a>>b) |
&= |
Bitwise "and" |
a&=b |
a=(a&b) |
^= |
Bitwise "exor" |
a^=b |
a=(a^b) |
|= |
Bitwise "or" |
a|=b |
a=(a|b) |
- externe tool voor integers: /usr/bin/expr
Spaties zijn verplicht met expr. expr is minder efficient dan let en (( )) want expr is een extern commando en start dus een subproces. Dat is in de huidige MultiCore computer helemaal niet erg voor een paar bewerkingen, maar voor enkele duizenden achter mekaar via lussen of functions, is expr toch minder efficient.
syntax:
expr <waarde1> <operator> <waarde2>
of
var=`expr <waarde1> <operator> <waarde2>`
var=$(expr <waarde1> <operator> <waarde2>)
De operatoren zijn dezelfde als voor let of (( ))
enkele voorbeelden
`expr` z=`expr $z + 3`
$(expr) z=$(expr $z + 3)
$ a=$(expr 1 + 3)
$ b=$(expr 2 - 1)
$ c=$(expr 10 / 2)
$ d=$(expr 20 % 3)
$ e=$(expr 10 \* 3)
$ f=`expr 6 + 3`
$ g=$(expr $a \* $c)
$ echo $a $b $c $d $e $f $g
4 1 5 2 30 9 20
Let op, de vermenigvuldiging moet voorafgegaan worden door de \ omdat * wordt gezien als een wildcard.
- externe tool voor reals: /usr/bin/bc
interactief:
$ bc
bc 1.06.94
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
17 / 7
2
quit
$ bc
bc 1.06.94
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
scale=3
17 / 7
2.428
quit
In het eerste voorbeeld hebben we de commando's in vetjes ingetikt. (bc, 17/7 en quit) Als resultaat kregen 2.
In het tweede voorbeeld hebben we vooraleer te rekenen scale=3 ingetikt.
Het gevolg is dat het resultaat op 3 cijfers nauwkeurig werd berekend.
via een pipe:
$ echo "scale=5; 17/7" | bc
2.42857
in een script:
a=$(echo "scale=10; 17/7" | bc)
echo $a
2.4285714285
of ook
pi=$(echo "scale=10; 4*a(1)" | bc -l)
echo $pi
3.1415926532
:-)
http://linux.about.com/od/commands/l/blcmdl1_bc.htm
- links
http://www.softpanorama.org/Scripting/Shellorama/arithmetic_expressions.shtml
http://hacktux.com/bash/math
http://www.linuxconfig.org/Bash_scripting_Tutorial
http://www.freeos.com/guides/lsst/ch02sec07.html
http://dsl.org/cookbook/cookbook_35.html#SEC480