Dziļāka funkciju sarežģītība ar čaulas skriptu - VII daļa


Mans iepriekšējais raksts “Funkciju izpratne un rakstīšana čaulas skriptos”, iespējams, ir devusi pamatideju par to, kā rakstīt funkcijas zem čaulas skriptiem. Tagad ir pienācis laiks iedziļināties funkcionālajās funkcijās, piemēram, lokālo mainīgo izmantošanā un rekursijā.

Kas padara mainīgo lokālu? Tas ir atkarīgs no konkrētā bloka, kurā mainīgais tiek deklarēts. Mainīgais, kas deklarēts kā lokāls , būs pieejams tajā koda blokā, kur tas parādās, t.i., tā darbības joma ir lokāla. Lai izskaidrotu šo lietu, apskatīsim vienu piemēru zemāk.

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

Izpildot iepriekš minēto skriptu, izeja būs.

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

Tas ir tāpēc, ka funkcija func vēl nav izsaukta, kamēr tika izpildīti pirmie 2 atbalss paziņojumi. Pēc funkcijas func izsaukšanas tie paši 2 atbalss paziņojumi rada atšķirīgu rezultātu. Tagad pēc tam varēja piekļūt mainīgajam j , kas tika deklarēts func iekšienē, nevis lokāls.

Tādējādi j vērtība kļūst par 20. Kā ir ar lokālo mainīgo i ? Tā kā tā darbības joma atradās funkcijas func iekšienē, 10. vērtībai nevarēja piekļūt no ārpuses. Ņemiet vērā, ka mainīgais j , kas parasti tiek deklarēts func iekšienē, pēc noklusējuma ir globāls.

Tagad jūs esat iepazinies ar lokālajiem mainīgajiem lielumiem un to izmantošanu funkciju blokos. Pārejam uz visinteresantāko sadaļu zem funkcijām - rekursija.

Funkcija, kas pati sevi sauc, parasti tiek saukta par rekursijas procedūru. Vai arī to var definēt kā algoritma izteikšanu, izmantojot tā paša algoritma vienkāršāku versiju. Apsveriet skaitļa faktoriāla atrašanas piemēru. Mēs zinām, ka n! = 1 x 2 x 3 x… x (n-1) x n. Tādējādi mēs varam uzrakstīt atkārtošanās saistību kā:

n! = (n-1)! x n

Tāpēc mums ir viegli rekursīvi izsaukt to pašu funkciju un izmantot katra zvana atgriešanās vērtību, lai reizinātu ar iepriekšējo rezultātu, t.i.

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

Šeit mēs mēģinām uzrakstīt skriptu skaitļa faktoriāla atrašanai, izmantojot vietējos mainīgos un rekursiju.

#!/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 ir lokāls mainīgais, ko izmanto, lai katru zvanu saglabātu katru n-1 vērtību. Šeit pamatnosacījums pārbauda, vai skaitlis ir vienāds ar nulli vai nē (jo 0! = 1 un faktoriāls nav noteikts negatīviem skaitļiem). Pienākot šim pamatnosacījumam, tas zvanītājam atdod vērtību 1. Tagad num = 1 un ret = 1 x 1 .

Šajā brīdī tas atgriež 1 zvanītājam. Tagad num = 2 un ret = 2 x 1 un tā tālāk. Visbeidzot, kad num = 5 atgriešanās vērtība būs 24, un gala rezultāts ir ret = 5 x 24 . Galīgais rezultāts 120 tiek nodots sākotnējam zvanītāja paziņojumam un tiek parādīts.

Iepriekš minētajā skriptā ir viena problēma. Kā es paskaidroju iepriekšējā rakstā, funkcijas nevar atgriezt lielus veselus skaitļus. Tāpēc lietotājiem ir jāatrod risinājums iepriekš minētajam jautājumam.

J. Vai mēs varam veikt rekursiju, neizmantojot lokālos mainīgos? Atbilde ir Jā.

Apskatiet šo piemēru, lai parādītu Fibonacci sēriju, izmantojot rekursiju. Pamata atkārtošanās saistība ir:

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

Iepriekš minētajā skriptā netiek izmantoti vietējie mainīgie. Es ceru, ka jūs varat saprast skripta plūsmu izpildes laikā.

Šeit vērtība 15 apzīmē parādāmo Fibonacci sērijas vārdu skaitu. Vai pamanījāt kaut ko īpašu saistībā ar iepriekš minētā skripta izpildi. Tas aizņem kādu laiku, vai ne? Rekursija skriptā ir lēnāka nekā rekursija programmēšanas valodās, piemēram, C.

Ar šo rakstu es plānoju noslēgt funkciju daļu čaulas skriptos. Esiet informēts par Tecmint, lai redzētu gaidāmos rakstus par masīviem un daudz ko citu ...