Website-Suche

Tiefere Einblicke in Funktionskomplexitäten mit Shell-Scripting – Teil VII


Mein vorheriger Artikel zum Thema „Funktionen in Shell-Skripten verstehen und schreiben“ hat Ihnen möglicherweise eine grundlegende Vorstellung davon vermittelt, wie Sie Funktionen unter Shell-Skripten schreiben. Jetzt ist es an der Zeit, tiefer in funktionale Features wie die Verwendung lokaler Variablen und Rekursion einzusteigen.

Lokale Variablen

Was macht eine Variable lokal? Es hängt von dem jeweiligen Block ab, in dem die Variable deklariert ist. Auf eine als local deklarierte Variable kann von dem Codeblock aus zugegriffen werden, in dem sie erscheint, d. h. ihr Gültigkeitsbereich ist lokal. Um dies zu erklären, schauen wir uns unten ein Beispiel an.

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

Beim Ausführen des obigen Skripts wird die Ausgabe angezeigt.

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

Dies liegt daran, dass die Funktion func noch nicht aufgerufen wurde, während die ersten 2 Echo-Anweisungen ausgeführt wurden. Nach dem Aufruf der Funktion func führen dieselben 2 Echo-Anweisungen zu einem anderen Ergebnis. Nun konnte anschließend auf die Variable j zugegriffen werden, die innerhalb von func und nicht lokal deklariert wurde.

Somit wird der Wert für j zu 20. Was ist mit der lokalen Variablen i? Da der Gültigkeitsbereich innerhalb der Funktion func lag, konnte von außen nicht auf den Wert 10 zugegriffen werden. Beachten Sie, dass die Variable j, die normalerweise in func deklariert wird, standardmäßig global ist.

Jetzt sind Sie mit lokalen Variablen und deren Verwendung innerhalb von Funktionsblöcken vertraut. Kommen wir zum interessantesten Abschnitt unter Funktionen, der Rekursion.

Was ist Rekursion?

Eine Funktion, die sich selbst aufruft, wird im Allgemeinen als Rekursionsverfahren bezeichnet. Oder es kann so definiert werden, dass es einen Algorithmus ausdrückt, indem eine einfachere Version desselben Algorithmus verwendet wird. Betrachten Sie das Beispiel der Ermittlung der Fakultät einer Zahl. Wir wissen, dass n!=1 x 2 x 3 x … x (n-1) x n. Somit können wir eine Wiederholungsrelation schreiben als:

n! = (n-1)! x n

Daher ist es für uns einfach, dieselbe Funktion rekursiv aufzurufen und den Rückgabewert jedes Aufrufs zur Multiplikation mit dem vorherigen Ergebnis zu verwenden, d. h.

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

Rekursion mit lokalen Variablen

Hier versuchen wir, ein Skript zum Finden der Fakultät einer Zahl mithilfe lokaler Variablen und Rekursion zu schreiben.

#!/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 ist eine lokale Variable, die zum Speichern jedes n-1-Werts bei jedem Aufruf verwendet wird. Hier prüft die Basisbedingung, ob die Zahl gleich Null ist oder nicht (da 0!=1 und Fakultät für negative Zahlen nicht definiert ist). Bei Erreichen dieser Grundbedingung gibt es den Wert 1 an seinen Aufrufer zurück. Jetzt ist num=1 und ret=1 x 1.

In diesem Moment gibt es 1 an seinen Anrufer zurück. Jetzt ist num=2 und ret=2 x 1 und so weiter. Wenn schließlich num=5 ist, beträgt der Rückgabewert 24 und das Endergebnis ist ret=5 x 24. Das Endergebnis 120 wird an die erste Anruferanweisung weitergegeben und angezeigt.

Im obigen Skript gibt es ein Problem. Wie ich im vorherigen Artikel erklärt habe, können Funktionen keine großen Ganzzahlen zurückgeben. Es bleibt also den Benutzern überlassen, eine Lösung für das oben genannte Problem zu finden.

F. Können wir eine Rekursion durchführen, ohne lokale Variablen zu verwenden? Die Antwort lautet Ja.

Rekursion ohne lokale Variablen

Sehen Sie sich das folgende Beispiel für die Darstellung der Fibonacci-Reihe mittels Rekursion an. Die grundlegende Wiederholungsbeziehung ist:

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

Im obigen Skript werden keine lokalen Variablen verwendet. Ich hoffe, Sie können den Ablauf des Skripts während der Ausführung verstehen.

Dabei stellt der Wert 15 die Anzahl der anzuzeigenden Terme der Fibonacci-Reihe dar. Ist Ihnen bei der Ausführung des obigen Skripts etwas Besonderes aufgefallen? Es dauert eine Weile, nicht wahr? Die Rekursion in einem Skript ist langsamer als eine Rekursion in Programmiersprachen wie C.

Mit diesem Artikel möchte ich den Funktionsteil beim Shell-Scripting abschließen. Bleiben Sie mit Tecmint auf dem Laufenden, um die kommenden Artikel zu Arrays und vielem mehr zu erhalten …