Zoeken op website

Dieper in functiecomplexiteiten met Shell Scripting – Deel VII


Mijn vorige artikel over “Functies in Shell-scripts begrijpen en schrijven” heeft je misschien een basisidee gegeven over hoe je functies onder shell-scripts schrijft. Nu is het tijd om dieper in te gaan op functionele kenmerken zoals het gebruik van lokale variabelen en recursie.

Lokale variabelen

Wat maakt een variabele lokaal? Het hangt af van dat specifieke blok waar de variabele wordt gedeclareerd. Een variabele die als lokaal is gedeclareerd, zal toegankelijk zijn vanuit dat codeblok waar deze verschijnt, dat wil zeggen dat de reikwijdte ervan lokaal is. Laten we, om dit uit te leggen, eens naar een voorbeeld hieronder kijken.

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

Bij het uitvoeren van het bovenstaande script zal de uitvoer zijn.

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

Dit komt omdat de functie func nog niet is aangeroepen terwijl de eerste 2 echo-instructies werden uitgevoerd. Na het aanroepen van de functie func produceren dezelfde twee echo-instructies een ander resultaat. Nu kon achteraf toegang worden verkregen tot de variabele j, die binnen func en niet lokaal was gedeclareerd.

De waarde voor j wordt dus 20. Hoe zit het met de lokale variabele i? Omdat het bereik ervan binnen de functie func lag, kon waarde 10 niet van buitenaf worden benaderd. Merk op dat de variabele j die normaal binnen func wordt gedeclareerd, standaard globaal is.

Nu bent u bekend met lokale variabelen en hoe u deze binnen functieblokken kunt gebruiken. Laten we verder gaan met het meest interessante gedeelte onder functies, de recursie.

Wat is recursie?

Een functie die zichzelf aanroept, wordt over het algemeen de recursieprocedure genoemd. Of het kan worden gedefinieerd als het uitdrukken van een algoritme door een eenvoudigere versie van datzelfde algoritme te gebruiken. Beschouw het voorbeeld van het vinden van faculteit van een getal. Dat weten we n!=1 x 2 x 3 x … x (n-1) x n. We kunnen dus een herhalingsrelatie schrijven als:

n! = (n-1)! x n

Het is dus gemakkelijk voor ons om recursief dezelfde functie aan te roepen en de retourwaarde van elke aanroep te gebruiken om te vermenigvuldigen met het vorige resultaat, d.w.z.

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

Recursie met behulp van lokale variabelen

Hier proberen we een script te schrijven voor het vinden van de faculteit van een getal met behulp van lokale variabelen en recursie.

#!/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 is een lokale variabele die wordt gebruikt om elke n-1 waarde bij elke aanroep op te slaan. Hier controleert de basisvoorwaarde of het getal gelijk is aan nul of niet (aangezien 0!=1 en faculteit niet is gedefinieerd voor negatieve getallen). Bij het bereiken van deze basisvoorwaarde retourneert het de waarde 1 aan de beller. Nu num=1 en ret=1 x 1.

Op dit moment stuurt hij 1 terug naar zijn beller. Nu num=2 en ret=2 x 1 enzovoort. Als num=5 de retourwaarde uiteindelijk 24 is en het eindresultaat ret=5 x 24. Het eindresultaat 120 wordt doorgegeven aan de initiële bellerverklaring en weergegeven.

Er is één probleem in het bovenstaande script. Zoals ik in het vorige artikel heb uitgelegd, kunnen functies geen grote gehele getallen retourneren. Het wordt dus aan de gebruikers overgelaten om een oplossing voor het bovenstaande probleem te vinden.

V. Kunnen we recursie uitvoeren zonder lokale variabelen te gebruiken? Het antwoord is Ja.

Recursie zonder lokale variabelen

Bekijk het volgende voorbeeld voor het weergeven van de Fibonacci-reeks met behulp van recursie. De fundamentele herhalingsrelatie is:

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

In het bovenstaande script worden geen lokale variabelen gebruikt. Ik hoop dat je de stroom van het script tijdens de uitvoering begrijpt.

Hier vertegenwoordigt de waarde 15 het aantal termen in de Fibonacci-reeks dat moet worden weergegeven. Is u iets speciaals opgevallen met betrekking tot de uitvoering van bovenstaand script. Het duurt even, nietwaar? Recursie in een script is langzamer dan een recursie in programmeertalen zoals C.

Met dit artikel ben ik van plan het functiegedeelte van shell-scripting af te ronden. Blijf op de hoogte met Tecmint voor de komende artikelen over arrays en nog veel meer...