Dublje u složenost funkcija sa shell skriptovima – VII dio


Moj prethodni članak o “Razumijevanje i pisanje funkcija u shell skriptama” možda vam je dao osnovnu ideju o tome kako pisati funkcije pod shell skriptama. Sada je vrijeme da uđemo dublje u funkcionalne karakteristike poput upotrebe lokalnih varijabli i rekurzije.

Lokalne varijable

Šta čini varijablu lokalnom? Zavisi od konkretnog bloka u kojem je varijabla deklarirana. Varijabla deklarirana kao lokalna bit će dostupna iz onog bloka koda gdje se pojavljuje, tj. njen opseg je lokalni. Da bismo objasnili ovu stvar pogledajmo jedan primjer u nastavku.

#!/bin/bash 

func( ) { 
	local i=10 
	j=20 
	echo "i from func = $i" 
	echo "j from func = $j" 
} 

echo "i outside func = $i" 
echo "j outside func = $j" 

func 

echo "i outside func = $i" 
echo "j outside func = $j" 

exit 0

Nakon izvršavanja gornje skripte izlaz će biti.

i outside func = 
j outside func = 
i from func = 10 
j from func = 20 
i outside func = 
j outside func = 20

To je zato što funkcija func još nije pozvana dok su prve 2 eho izjave bile izvršene. Nakon poziva funkcije func iste 2 eho izjave daju drugačiji rezultat. Sada se promenljivoj j, koja je deklarisana unutar func, a ne lokalno, može pristupiti naknadno.

Tako vrijednost za j postaje 20. Što je s lokalnom varijablom i? Pošto je njegov opseg bio unutar funkcije func, vrijednosti 10 nije se moglo pristupiti izvana. Imajte na umu da je varijabla j koja je normalno deklarirana unutar func globalna po defaultu.

Sada ste upoznati s lokalnim varijablama i kako ih koristiti unutar funkcionalnih blokova. Pređimo na najzanimljiviji dio pod funkcijama, rekurziju.

Šta je rekurzija?

Sama funkcija poziva se općenito naziva rekurzivnom procedurom. Ili se može definirati kao izražavanje algoritma korištenjem jednostavnije verzije tog istog algoritma. Razmotrimo primjer pronalaženja faktorijala broja. Znamo dan!=1 x 2 x 3 x … x (n-1) x n. Tako možemo zapisati rekurentnu relaciju kao:

n! = (n-1)! x n

Tako da nam je lako rekurzivno pozvati istu funkciju i koristiti povratnu vrijednost iz svakog poziva da pomnožimo s prethodnim rezultatom, tj.

5! = 4! x 5
4! = 3! x 4
3! = 2! x 3
2! = 1! x 2
1! = 0! x 1

Rekurzija koristeći lokalne varijable

Ovdje pokušavamo napisati skriptu za pronalaženje faktorijala broja koristeći lokalne varijable i rekurziju.

#!/bin/bash 

fact( ) { 
	local num=$1 
	if [ $num -eq 0 ]; then 
		ret=1 
	else 
		temp=$((num-1)) 
		fact $temp 
		ret=$((num*$?)) 
	fi 
	return $ret 
} 

fact 5 

echo "Factorial of 5 = $?" 

exit 0

num je lokalna varijabla koja se koristi za pohranjivanje svake n-1 vrijednosti za svaki poziv. Ovdje osnovni uvjet provjerava da li je broj jednak nuli ili ne (pošto je 0!=1 i faktorijel nije definiran za negativne brojeve). Po dolasku ovog osnovnog uslova vraća vrijednost 1 svom pozivaocu. Sada num=1 i ret=1 x 1.

U ovom trenutku vraća 1 svom pozivaocu. Sada num=2 i ret=2 x 1 i tako dalje. Konačno kada je num=5 povratna vrijednost će biti 24, a konačni rezultat je ret=5 x 24. Konačni rezultat 120 se prosljeđuje do početne izjave pozivaoca i prikazuje se.

Postoji jedan problem u gornjoj skripti. Kao što sam objasnio u prethodnom članku, funkcije ne mogu vratiti velike cijele brojeve. Dakle, prepušteno je korisnicima da pronađu rješenje za gornji problem.

P. Možemo li izvesti rekurziju bez korištenja lokalnih varijabli? Odgovor jeDa.

Rekurzija bez lokalnih varijabli

Pogledajte sljedeći primjer za prikaz Fibonačijevog niza pomoću rekurzije. Osnovna relacija recidiva je:

fib(0) = 0 
fib(1) = 1 
else 
	fib(n) = fib(n-1) + fib(n-2)

Fibonacci series using recursion

#!/bin/bash 

fib( ) { 
	a=$1 
	if [ $a -lt 2 ]; then 
		echo $a 
	else 
		((--a)) 
		b=$(fib $a) 

		((--a)) 
		c=$(fib $a) 

		echo $((b+c)) 
	fi 
} 

for i in $(seq 0 15) 
do 
	out=$(fib $i) 
	echo $out 
done 

exit 0

U gornjoj skripti se ne koriste lokalne varijable. Nadam se da možete razumjeti tok skripte tokom izvršavanja.

Ovdje vrijednost 15 predstavlja broj pojmova u Fibonaccijevom nizu koji će se prikazati. Da li ste primijetili nešto posebno u vezi s izvršavanjem gornje skripte. Potrebno je neko vrijeme, zar ne? Rekurzija u skripti je sporija od rekurzije u programskim jezicima kao što je C.

Ovim člankom planiram zaključiti dio funkcija u shell skriptiranju. Budite u toku sa Tecmintom kako biste imali nadolazeće članke o nizovima i još mnogo toga…