Funktsiooni keerukuse süvendamine shelliskriptide abil - VII osa


Minu eelmine artikkel teemal “Funktsioonide mõistmine ja kirjutamine Shell-skriptides” võis anda teile põhiidee, kuidas funktsioone shelliskriptide alla kirjutada. Nüüd on aeg süveneda funktsionaalsetesse omadustesse, nagu kohalike muutujate kasutamine ja rekursioon.

Mis muudab muutuja lokaalseks? See sõltub konkreetsest plokist, kus muutuja deklareeritakse. Muutujaks, mis on deklareeritud kui kohalik , pääseb juurde sellest koodiplokist, kus see ilmub, st selle ulatus on kohalik. Selle asja selgitamiseks uurime allpool ühte näidet.

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

Ülaltoodud skripti käivitamisel on väljund.

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

Seda seetõttu, et funktsiooni func pole veel kutsutud, kui esimesed 2 kajalauset olid täidetud. Pärast funktsiooni func kutsumist annavad sama 2 kajalauset erineva tulemuse. Nüüd pääseb tagantjärele juurde muutujale j , mis oli deklareeritud func sees ja mitte kohalik.

Nii saab väärtus j väärtuseks 20. Aga kohalik muutuja i ? Kuna selle ulatus oli funktsiooni func sees, ei olnud väärtusele 10 võimalik väljastpoolt juurde pääseda. Pange tähele, et j tavaliselt deklareeritud muutuja func on vaikimisi globaalne.

Nüüd olete tuttav lokaalsete muutujatega ja nende kasutamisega funktsiooniplokkides. Liigume funktsioonide all kõige huvitavamale osale rekursioonile.

Ise kutsuvat funktsiooni nimetatakse tavaliselt rekursiooniprotseduuriks. Või võib seda defineerida algoritmi väljendajana, kasutades sama algoritmi lihtsamat versiooni. Mõelgem näiteks arvu faktori leidmise näitele. Me teame, et n! = 1 x 2 x 3 x… x (n-1) x n. Seega saame korduvussuhte kirjutada järgmiselt:

n! = (n-1)! x n

Seega on meil lihtne sama funktsiooni rekursiivselt kutsuda ja kasutada iga kõne tagasiväärtust korrutamaks eelmise tulemusega, st

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

Siin proovime kirjutada skripti arvu faktori leidmiseks kohalike muutujate ja rekursiooni abil.

#!/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 on lokaalne muutuja, mida kasutatakse iga kõne iga n-1 väärtuse salvestamiseks. Siin kontrollib põhitingimus, kas arv on nulliga võrdne või mitte (kuna 0! = 1 ja negatiivsete arvude korral pole faktoriaal määratletud). Selle põhitingimuse saabumisel tagastab see helistajale väärtuse 1. Nüüd num = 1 ja ret = 1 x 1 .

Sel hetkel tagastab ta helistajale 1. Nüüd num = 2 ja ret = 2 x 1 ja nii edasi. Lõpuks, kui num = 5 on tagastusväärtus 24 ja lõpptulemus on ret = 5 x 24 . Lõpptulemus 120 edastatakse esialgsele helistaja väljavõttele ja kuvatakse.

Ülalolevas skriptis on üks probleem. Nagu eelmises artiklis selgitasin, ei saa funktsioonid tagastada suuri täisarvusid. Seega jääb kasutajatele ülesandeks leida ülaltoodud probleemile lahendus.

K. Kas saame rekursiooni sooritada ilma kohalikke muutujaid kasutamata? Vastus on jah.

Vaadake järgmist näidet Fibonacci seeria kuvamiseks rekursiooni abil. Korduvuse põhisuhe on:

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

Ülalolevas skriptis ei kasutata kohalikke muutujaid. Loodan, et saate skripti käigust täitmise ajal aru.

Siin tähistab väärtus 15 Fibonacci seerias kuvatavate terminite arvu. Kas märkasite ülaltoodud skripti käivitamisel midagi erilist? See võtab natuke aega, kas pole? Rekursioon skriptis on aeglasem kui rekursioon programmeerimiskeeltes nagu C.

Selle artikliga kavatsen lõpetada funktsioonide osa shelliskriptides. Hoidke end Tecmintiga kursis, et saada artikleid massiivide kohta ja palju muud ...