Dublje u složenost funkcija s skriptiranjem ljuske – dio VII


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

Lokalne varijable

Što varijablu čini lokalnom? Ovisi o tom određenom bloku u kojem je varijabla deklarirana. Varijabla deklarirana kao lokalna bit će dostupna iz onog bloka koda u kojem se pojavljuje, tj. njen opseg je lokalni. Kako 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

Prilikom 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 echo izjave bile izvršene. Nakon poziva funkcije func iste 2 echo izjave daju drugačiji rezultat. Sada se varijabli j, koja je deklarirana unutar func a ne local, moglo pristupiti naknadno.

Tako vrijednost za j postaje 20. Što je s lokalnom varijablom i? Budući da je njezin opseg bio unutar funkcije func, vrijednosti 10 nije se moglo pristupiti izvana. Imajte na umu da je varijabla j koja se obično deklarira unutar func prema zadanim postavkama globalna.

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

Što je rekurzija?

Sam poziv funkcije općenito se naziva rekurzijskom procedurom. Ili se može definirati kao izražavanje algoritma korištenjem jednostavnije verzije tog istog algoritma. Razmotrimo primjer nalaženja faktorijela broja. Znamo ton!=1 x 2 x 3 x … x (n-1) x n. Stoga možemo napisati odnos ponavljanja kao:

n! = (n-1)! x n

Dakle, lako nam je rekurzivno pozvati istu funkciju i koristiti povratnu vrijednost iz svakog poziva za množenje 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 korištenjem lokalnih varijabli

Ovdje pokušavamo napisati skriptu za pronalaženje faktorijela 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 vrijednosti n-1 pri svakom pozivu. Ovdje osnovni uvjet provjerava je li broj jednak nuli ili ne (jer je 0!=1 i faktorijel nije definiran za negativne brojeve). Kada dođe do ovog osnovnog uvjeta, vraća vrijednost 1 svom pozivatelju. Sada num=1 i ret=1 x 1.

U ovom trenutku pozivatelju vraća 1. 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 prenosi se do početne izjave pozivatelja i prikazuje se.

Postoji jedan problem u gornjoj skripti. Kao što sam objasnio u prethodnom članku, funkcije ne mogu vratiti velike cijele brojeve. Stoga je prepušteno 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 Fibonaccijevog niza pomoću rekurzije. Osnovna relacija ponavljanja 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 ne koriste se lokalne varijable. Nadam se da možete razumjeti tijek skripte tijekom izvođenja.

Ovdje vrijednost 15 predstavlja broj članova u Fibonaccijevom nizu koji će se prikazati. Jeste li 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 s funkcijama u skriptiranju ljuske. Budite u tijeku s Tecmintom kako biste imali nadolazeće članke o nizovima i još mnogo toga…