Giliau į funkcijų sudėtingumą su „Shell Scripting“ - VII dalis


Ankstesnis mano straipsnis „Funkcijų supratimas ir rašymas„ Shell “scenarijuose“ galėjo pateikti pagrindinę idėją, kaip rašyti funkcijas pagal „shell“ scenarijus. Dabar laikas gilintis į tokias funkcines savybes kaip vietinių kintamųjų naudojimas ir rekursija.

Kuo kintamasis tampa lokalus? Tai priklauso nuo to konkretaus bloko, kuriame deklaruojamas kintamasis. Kintamasis, deklaruojamas kaip vietinis , bus pasiekiamas iš to kodo bloko, kur jis pasirodo, t. Y. Jo taikymo sritis yra vietinė. Norėdami paaiškinti šį dalyką, pažvelkime į vieną toliau pateiktą pavyzdį.

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

Vykdant pirmiau pateiktą scenarijų išvestis bus.

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

Taip yra todėl, kad funkcija func dar nebuvo iškviesta, kol buvo vykdomi pirmieji 2 aido teiginiai. Paskambinus funkcijai func , tie patys 2 aido teiginiai duoda kitokį rezultatą. Dabar po to galima pasiekti kintamąjį j , kuris buvo paskelbtas func viduje, o ne vietinis.

Taigi j reikšmė tampa 20. O vietinis kintamasis i ? Kadangi jo taikymo sritis buvo funkcijos func viduje, 10 vertės nepavyko pasiekti iš išorės. Atminkite, kad kintamasis j , paprastai deklaruojamas func viduje, pagal numatytuosius nustatymus yra visuotinis.

Dabar esate susipažinę su vietiniais kintamaisiais ir kaip juos naudoti funkcijų blokuose. Pereikime prie įdomiausio funkcijų skyriaus - rekurso.

Pati paskambinanti funkcija paprastai vadinama rekursijos procedūra. Arba tai galima apibrėžti kaip išreiškiantį algoritmą naudojant paprastesnę to paties algoritmo versiją. Apsvarstykite skaičiaus faktorialo radimo pavyzdį. Mes žinome, kad n! = 1 x 2 x 3 x… x (n-1) x n. Taigi mes galime parašyti pasikartojimo santykį kaip:

n! = (n-1)! x n

Taigi mums lengva rekursyviai iškviesti tą pačią funkciją ir panaudoti kiekvieno skambučio grąžinimo vertę padauginti iš ankstesnio rezultato, t.

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

Čia mes bandome parašyti scenarijų, kaip surasti faktoriaus skaičių naudojant vietinius kintamuosius ir rekursiją.

#!/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 yra vietinis kintamasis, naudojamas kiekvienam skambučiui išsaugoti kiekvieną n-1 vertę. Čia pagrindinė sąlyga patikrina, ar skaičius lygus nuliui, ar ne (nes 0! = 1, o neigiamiems skaičiams faktorialas nėra apibrėžtas). Gavęs šią pagrindinę sąlygą, jis grąžina skambinančiajam 1 vertę. Dabar num = 1 ir ret = 1 x 1 .

Šiuo metu jis grąžina 1 skambinančiajam. Dabar num = 2 ir ret = 2 x 1 ir pan. Galiausiai, kai num = 5 grąžos vertė bus 24, o galutinis rezultatas bus ret = 5 x 24 . Galutinis rezultatas 120 perduodamas pradiniam skambinančiojo teiginiui ir rodomas.

Pirmiau pateiktame scenarijuje yra viena problema. Kaip paaiškinau ankstesniame straipsnyje, funkcijos negali grąžinti didelių sveikųjų skaičių. Taigi vartotojams paliekama rasti pirmiau minėtos problemos sprendimą.

Klausimas. Ar galime atlikti rekursiją nenaudodami vietinių kintamųjų? Atsakymas yra taip.

Peržiūrėkite šį pavyzdį, kaip rodyti „Fibonacci“ seriją naudojant rekursiją. Pagrindinis pasikartojimo ryšys yra:

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

Ankstesniame scenarijuje nenaudojami jokie vietiniai kintamieji. Tikiuosi, kad galite suprasti scenarijaus eigą vykdymo metu.

Čia vertė 15 rodo rodomų „Fibonacci“ serijos terminų skaičių. Ar pastebėjote ką nors ypatingo, susijusio su aukščiau esančio scenarijaus vykdymu. Tai užtrunka, ar ne? Rekursija scenarijuje yra lėtesnė nei rekursija tokiomis programavimo kalbomis kaip C.

Šiuo straipsniu planuoju užbaigti apvalkalo scenarijų funkcijų dalį. Nuolat atnaujinkite „Tecmint“, kad gautumėte būsimus straipsnius apie masyvus ir daug daugiau ...