Profundizar en las complejidades de las funciones con secuencias de comandos de shell - Parte VII


Mi artículo anterior sobre "Comprensión y escritura de funciones en scripts de shell" podría haberle dado una idea básica sobre cómo escribir funciones en scripts de shell. Ahora es el momento de profundizar en las características funcionales como el uso de variables locales y la recursividad.

¿Qué hace que una variable sea local? Depende de ese bloque en particular donde se declara la variable. Una variable declarada como local será accesible desde ese bloque de código donde aparece, es decir, su alcance es local. Para explicar esto, veamos un ejemplo a continuación.

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

Al ejecutar el script anterior, la salida será.

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

Esto se debe a que la función func aún no se ha llamado mientras se ejecutaron las 2 primeras declaraciones de eco. Después de llamar a la función func , las mismas 2 declaraciones de eco producen un resultado diferente. Ahora se puede acceder a la variable j , que fue declarada dentro de func y no local, posteriormente.

Por lo tanto, el valor de j se convierte en 20. ¿Qué pasa con la variable local i ? Dado que su alcance estaba dentro de la función func , no se podía acceder al valor 10 desde fuera. Tenga en cuenta que la variable j normalmente declarada dentro de func es global por defecto.

Ahora está familiarizado con las variables locales y cómo usarlas dentro de los bloques de funciones. Pasemos a la sección más interesante bajo funciones, la recursividad.

Una función que se llama a sí misma generalmente se denomina procedimiento de recursividad. O se puede definir como la expresión de un algoritmo utilizando una versión más simple de ese mismo algoritmo. Considere el ejemplo de encontrar factorial de un número. ¡Sabemos que n! u003d 1 x 2 x 3 x… x (n-1) x norte. Por tanto, podemos escribir una relación de recurrencia como:

n! = (n-1)! x n

Entonces, es fácil para nosotros llamar de forma recursiva a la misma función y usar el valor de retorno de cada llamada para multiplicar con el resultado anterior, es decir,

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

Aquí intentamos escribir un script para encontrar factorial de un número usando variables locales y recursividad.

#!/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 es una variable local que se utiliza para almacenar cada valor n-1 en cada llamada. Aquí la condición base verifica si el número es igual a cero o no (ya que 0! u003d 1 y el factorial no está definido para números negativos). Al llegar a esta condición base, devuelve el valor 1 a su llamador. Ahora num u003d 1 y ret u003d 1 x 1 .

En este instante devuelve 1 a su llamador. Ahora num u003d 2 y ret u003d 2 x 1 y así sucesivamente. Finalmente, cuando num u003d 5 el valor de retorno sea 24 y el resultado final sea ret u003d 5 x 24 . El resultado final 120 se transmite a la declaración inicial de la persona que llama y se muestra.

Hay un problema en el script anterior. Como expliqué en el artículo anterior, las funciones no pueden devolver números enteros grandes. Así que queda en manos de los usuarios encontrar una solución para el problema anterior.

Mire el siguiente ejemplo para mostrar la serie de Fibonacci usando recursividad. La relación de recurrencia básica es:

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

No se utilizan variables locales en el script anterior. Espero que pueda comprender el flujo del script durante la ejecución.

Aquí, el valor 15 representa el número de términos de la serie de Fibonacci que se mostrarán. ¿Notó algo especial con respecto a la ejecución del script anterior? Lleva un tiempo, ¿no? La recursividad en un script es más lenta que una recursividad en lenguajes de programación como C.

Con este artículo, planeo concluir la parte de funciones en el script de shell. Manténgase actualizado con Tecmint para tener los próximos artículos sobre matrices y mucho más ...