Naredba 'expr'

Naredba 'expr' dolazi nam u paketu coreutils. Nećemo je prečesto koristiti, ali će dobro doći ako pokušavamo napisati neku shell skriptu. Da ne duljimo, naredba expr obavlja jednostavne računske operacije u skriptama ili u naredbenoj liniji.


U slučaju bilo kakve kompleksnije računske operacije isplati se pokrenuti neki GUI program ili jednostavno uzeti telefon koji je uvijek pri ruci (i non-smartphone telefon ima kalkulator). No, oni ne mogu automatski izračunati vrijednosti u skripti, niti mogu biti brži nego što vi stignete otkucati:

$ expr 86400 / 60 / 60
24

Ukoliko ste prepoznali vrijednost 86400, radi se o defaultnom vremenu (TTL) za zonu u DNS-u i izražena je u sekundama. Kada to podijelimo sa 60 (minute) i jos jednom 60 (sati), dobit ćemo da je ta vrijednost zapravo 24 sata iliti jedan dan. Ovu smo naredbu neki od nas pokretali nebrojeno puta i znaju je naizust. Ovo je, po našem mišljenju, jedna od najčešćih primjena naredbe expr (konverzija vremena). Vrijeme u sekundama se nalazi u konfiguracijama mnogih servisa na serveru, a ne podržavaju svi skraćeni oblik, primjerice "1h" ili "1d".

Dakako, naredba expr podržava i druge računske operacije:

$ expr 10 - 5
5
$ expr 5 + 5
10

No, kod množenja (znak je '*', asterisk) postoji problem, jer se asterisk mora skloniti od shella (ljuske), koji će to pokušati protumačiti kao metakarakter (wildcard, joker znak). Zato ga je potrebno skloniti (escapeati):

$ expr 5 \* 5
25
$ expr 5 "*" 5
25

Dakle, treba paziti na ovu činjenicu (a nije baš da je to rijetkost što se shella tiče). Nažalost, jednostavnost upotrebe naredbe expr je kod množenja nešto manja zbog ove činjenice, dok se znak dijeljenja "/" nalazi na numeričkom dijelu tipkovnice i lako je dostupan.

Naredba expr ima još operatora, ali ih nećemo sve objasniti (odnosno ostavit ćemo ovo za sam kraj članka). Da pogledamo koji se operatori koriste u realnoj situaciji, grepali smo sve instalacijske skripte na Debianu i dobili smo ovakav ispis (izbacili smo duple retke):

clamav-freshclam.postinst:          cronhour="`expr 24 / $RET`"
grub-pc.postinst:    size="$(expr "$num_sectors" \* "$sector_size" / 1000 / 1000)"
ossec-hids-cn.postinst: <rule id="$(expr "$sid" + 1)" level="0">
sudo.postinst:  gid=`expr $gid + 1`
x11-common.postinst:    if ! expr "$1" : "[[:digit:]]\+$" > /dev/null 2>&1; then
x11-common.postinst:    if expr "$1" : '.*[!$&()*;<>?|].*' > /dev/null 2>&1; then

Dakle, paket freshclam koristi dijeljenje, grub-pc koristi množenje i dijeljenje, a sudo i ossec-hids samo trivijano zbrajanje.

No, x11-common (paket koji uvijek imate, iako nemate grafičko sučelje) koristi operator ":".  Ovaj operator uspoređuje niz znakova (string) sa regularnim izrazom, i ukoliko se podudaraju, ispisuje znak "1":

$ expr "123456" : [[:digit:]]
1
$ expr "perica" : [[:digit:]]
0
$ expr "perica1" : [[:digit:]]
0

U suprotnom, ispisuje se "0". Regularni izraz "[[:digit:]]" označava da se u stringu traže samo brojke, dok regularni izraz ".*[!$&()*;<>?|].*" traži sve te navedene znakove u stringu, ukoliko ste se zapitali što točno znači taj regularni izraz. Ukoliko nađe neki od tih specijalnih znakova, ispisat će duljinu stringa.

Postoji još operatora, poglavito onih za uspoređivanje: <, >, <=, => itd. I njih treba skloniti od shella, pa su pomalo nezgrapni za pisanje. Nećemo ih spominjati, jer se u shell skriptama obično koristi moćnija naredba "test".

Osim uspoređivanja, expr može izračunati modulo (operator "%"), pronaći fiksni string u drugom stringu (operator "substr"), poziciju traženog karaktera unutar stringa ("index") i duljinu stringa ("length").

No, za ove operacije se obično rabe druge naredbe (ili awk), a mi smo se odlučili zadržati na najčešćoj primjeni, u što se i sami možete uvjeriti pogledavši što se koristi u instalacijskim skriptama Debianovih paketa.

 

Kuharice: 
Kategorije: 
Vote: 
0
No votes yet