Syvemmälle toimintojen monimutkaisuuteen Shell-komentosarjan avulla – Osa VII


Edellinen artikkelini "Shell-komentosarjojen funktioiden ymmärtäminen ja kirjoittaminen" saattoi antaa sinulle perusidean funktioiden kirjoittamisesta komentotulkkikomentosarjojen alle. Nyt on aika päästä syvemmälle toiminnallisiin ominaisuuksiin, kuten paikallisten muuttujien käyttöön ja rekursioon.

Paikalliset muuttujat

Mikä tekee muuttujasta paikallisen? Se riippuu siitä tietystä lohkosta, jossa muuttuja on ilmoitettu. Muuttuja, joka on ilmoitettu paikalliseksi, on käytettävissä siitä koodilohkosta, jossa se esiintyy, eli sen laajuus on paikallinen. Selvittääksemme tämän asian, tarkastellaan yhtä esimerkkiä alla.

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

Kun yllä oleva komentosarja suoritetaan, tulos on.

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

Tämä johtuu siitä, että funktiota func ei ole vielä kutsuttu, kun kaksi ensimmäistä echo-lausetta suoritettiin. Kun funktiota func on kutsuttu, samat 2 echo-lausetta tuottavat erilaisen tuloksen. Nyt muuttujaa j, joka ilmoitettiin funcissa eikä paikallisessa, voitiin käyttää myöhemmin.

Tällöin j:n arvoksi tulee 20. Entä paikallinen muuttuja i? Koska sen laajuus oli funktion func sisällä, arvoa 10 ei voitu käyttää ulkopuolelta. Huomaa, että muuttuja j, joka tavallisesti ilmoitetaan sisällä func, on oletuksena yleinen.

Nyt tunnet paikalliset muuttujat ja niiden käytön toimintolohkojen sisällä. Siirrytään mielenkiintoisimpaan funktioiden osaan, rekursioon.

Mikä on rekursio?

Itse kutsuvaa funktiota kutsutaan yleensä rekursioproseduuriksi. Tai se voidaan määritellä ilmaisemaan algoritmia käyttämällä saman algoritmin yksinkertaisempaa versiota. Harkitse esimerkkiä luvun kertoimen löytämisestä. Tiedämme, että n!=1 x 2 x 3 x … x (n-1) x n. Näin ollen voimme kirjoittaa toistuvuusrelaation seuraavasti:

n! = (n-1)! x n

Joten meidän on helppo kutsua rekursiivisesti samaa funktiota ja käyttää jokaisen kutsun palautusarvoa kertoaksemme edellisen tuloksen kanssa, ts.

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

Rekursio paikallisten muuttujien avulla

Tässä yritetään kirjoittaa skripti luvun faktoraalin löytämiseksi käyttämällä paikallisia muuttujia ja rekursiota.

#!/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 paikallinen muuttuja, jota käytetään kunkin puhelun jokaisen n-1-arvon tallentamiseen. Tässä perusehto tarkistaa, onko luku nolla vai ei (koska 0!=1 ja kertoimia ei ole määritetty negatiivisille luvuille). Saavuttuaan tähän perusehtoon se palauttaa arvon 1 kutsujalleen. Nyt num=1 ja ret=1 x 1.

Tällä hetkellä se palauttaa 1 soittajalleen. Nyt num=2 ja ret=2 x 1 ja niin edelleen. Lopuksi, kun num=5, palautusarvo on 24 ja lopputulos on ret=5 x 24. Lopputulos 120 välitetään alkuperäiseen soittajan lausuntoon ja näytetään.

Yllä olevassa skriptissä on yksi ongelma. Kuten edellisessä artikkelissa selitin, funktiot eivät voi palauttaa suuria kokonaislukuja. Joten käyttäjien tehtävänä on löytää ratkaisu yllä olevaan ongelmaan.

K. Voimmeko suorittaa rekursion ilman paikallisia muuttujia? Vastaus on Kyllä.

Rekursio ilman paikallisia muuttujia

Katso seuraava esimerkki Fibonacci-sarjan näyttämisestä rekursion avulla. Toistumisen perussuhde 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

Yllä olevassa skriptissä ei käytetä paikallisia muuttujia. Toivon, että ymmärrät komentosarjan kulkua suorituksen aikana.

Tässä arvo 15 edustaa näytettävien Fibonacci-sarjan termien määrää. Huomasitko jotain erityistä yllä olevan skriptin suorittamisessa. Se kestää jonkin aikaa, eikö niin? Skriptin rekursio on hitaampaa kuin rekursio ohjelmointikielissä, kuten C.

Tällä artikkelilla aion päättää komentotulkkikomentosarjan funktioiden osan. Pysy ajan tasalla Tecmintistä, niin saat tulevat artikkelit taulukoista ja paljon muuta…