Weboldal keresés

A Shell Scripting funkcióbonyolultságaiba mélyebben – VII. rész


A „Funkciók megértése és írása a Shell Scripts-ben” című korábbi cikkem talán egy alapötletet adott a függvények shell szkriptek alá írásához. Itt az ideje, hogy elmélyüljünk az olyan funkcionális funkciókban, mint a helyi változók használata és a rekurzió.

Helyi változók

Mitől lokális a változó? Ez attól a blokktól függ, ahol a változó deklarálva van. A localként deklarált változó attól a kódblokktól lesz elérhető, ahol megjelenik, azaz a hatóköre helyi. Ennek magyarázata érdekében nézzünk meg egy példát az alábbiakban.

#!/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

A fenti szkript végrehajtásakor a kimenet a következő lesz.

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

Ennek az az oka, hogy a func függvény még nem hívta meg az első 2 echo utasítás végrehajtását. A func függvény meghívása után ugyanaz a 2 echo utasítás eltérő eredményt ad. Most a j változó, amely a func-on belül volt deklarálva, és nem helyi, utólag elérhető volt.

Így a j értéke 20 lesz. Mi a helyzet az i helyi változóval? Mivel a hatóköre a func függvényen belül volt, a 10 értéket kívülről nem lehetett elérni. Vegye figyelembe, hogy a j változó, amelyet általában a func-ban deklarálnak, alapértelmezés szerint globális.

Most már ismeri a helyi változókat és azok funkcióblokkon belüli használatát. Térjünk át a függvények alatt a legérdekesebb részre, a rekurzióra.

Mi az a rekurzió?

Magát a függvényhívást általában rekurziós eljárásnak nevezik. Vagy definiálható úgy is, hogy egy algoritmust fejez ki ugyanazon algoritmus egyszerűbb változatának használatával. Tekintsük a szám faktoriális meghatározásának példáját. Tudjuk, hogy n!=1 x 2 x 3 x … x (n-1) x n. Így felírhatunk egy ismétlődési relációt a következőképpen:

n! = (n-1)! x n

Így könnyű rekurzív módon meghívni ugyanazt a függvényt, és az egyes hívásokból származó visszatérési értékkel megszorozni az előző eredménnyel, azaz.

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

Rekurzió helyi változók használatával

Itt megpróbálunk egy szkriptet írni egy szám faktoriálisának megtalálásához lokális változók és rekurzió segítségével.

#!/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

A num egy helyi változó, amely az egyes hívások n-1 értékeinek tárolására szolgál. Itt az alapfeltétel ellenőrzi, hogy a szám egyenlő-e nullával vagy sem (mivel 0!=1, és a faktoriális nincs definiálva negatív számoknál). Az alapfeltétel elérésekor az 1 értéket adja vissza hívójának. Most szám=1 és ret=1 x 1.

Ebben a pillanatban visszaküldi az 1-et a hívójának. Most szám=2 és ret=2 x 1 és így tovább. Végül, ha szám=5, a visszatérési érték 24 lesz, a végeredmény pedig ret=5 x 24. A végeredmény 120 átkerül a kezdeti hívó nyilatkozatba, és megjelenik.

Egy probléma van a fenti szkriptben. Ahogy az előző cikkben kifejtettem, a függvények nem adhatnak vissza nagy egész számokat. Így a felhasználókra van bízva, hogy megoldást találjanak a fenti problémára.

K. Végezhetünk-e rekurziót helyi változók használata nélkül? A válaszIgen.

Rekurzió helyi változók nélkül

Tekintse meg a következő példát a Fibonacci-sorozat rekurziós megjelenítésére. Az alapvető ismétlődési összefüggés a következő:

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

A fenti szkriptben nem használnak helyi változókat. Remélem, megérti a szkript folyamatát a végrehajtás során.

Itt a 15 érték a Fibonacci-sorozat megjelenítendő kifejezéseinek számát jelenti. Észrevett valami különlegeset a fenti szkript végrehajtásával kapcsolatban? Eltart egy darabig, nem? A szkriptben a rekurzió lassabb, mint az olyan programozási nyelvekben, mint a C.

Ezzel a cikkel a shell scripting függvények részét tervezem lezárni. Maradjon naprakész a Tecmint segítségével, hogy a közelgő cikkeket a tömbökről és még sok másról olvashatja…