Búsqueda de sitios web

Comprensión y escritura de funciones en Shell Scripts - Parte VI


Las funciones juegan un papel importante en cualquier lenguaje de programación. Como muchos lenguajes de programación reales, bash tiene funciones que se utilizan con una implementación limitada.

¿Qué son las funciones?

En programación, las funciones son secciones nombradas de un programa que realiza una tarea específica. En este sentido, una función es un tipo de procedimiento o rutina. Cuando se llama a una función, el programa abandona la sección actual de código y comienza a ejecutar la primera línea dentro de la función. Siempre que haya código repetitivo o cuando una tarea se repita, considere usar una función en su lugar.

Por ejemplo, considere el caso en el que necesitamos encontrar el factorial de un número en varias etapas de un programa en particular. En lugar de escribir el código completo (para calcular el factorial) cada vez, podemos escribir esa parte del código que calcula el factorial una vez dentro de un bloque y reutilizar el mismo en múltiples ocasiones.

¿Por qué escribimos funciones?

  1. Nos ayuda a reutilizar el código.
  2. Mejorar la legibilidad del programa.
  3. Uso eficiente de variables dentro del programa.
  4. Nos permite probar el programa parte por parte.
  5. Muestra el programa como un conjunto de subpasos.
Funciones en scripts de shell

La sintaxis general para escribir funciones en un script de shell incluye las siguientes formas.

function func_name {
	. . .
	commands
	. . .
}

or

func_name ( ) {
	. . .
	commands
	. . .
}

Opening curly braces can also be used in the second line as well.

func_name ( )
{
	. . .
	commands
	. . .
}

Siempre podrá escribir comandos válidos dentro de estos bloques de funciones como lo hacemos normalmente en los scripts de shell. Ahora intentemos escribir un script simple con una pequeña función dentro.

#!/bin/bash

call_echo ( ) {
	echo ‘This is inside function’
}

op=$1

if [ $# -ne 1 ]; then
	echo "Usage: $0 <1/0>"
else
	if [ $1 = 0 ] ; then
		echo ‘This is outside function’
	elif [ $1 = 1 ] ; then
		call_echo
	else
		echo ‘Invalid argument’
	fi
fi

exit 0

La definición de la función debe preceder a la primera llamada a la misma. No hay nada como "declarar la función" antes de llamarla. Y siempre podemos anidar funciones dentro de funciones.

Nota: - Escribir funciones vacías siempre produce errores de sintaxis.

Cuando la misma función se define varias veces, lo que se invoca es la versión final. Tomemos un ejemplo.

#!/bin/bash

func_same ( ) {
	echo ‘First definition’
}

func_same ( ) {
	echo ‘Second definition’
}

func_same

exit 0
Funciones que toman parámetros y devuelven valores.

Profundicemos considerando funciones que toman parámetros y devuelven valores. Para devolver un valor de una función utilizamos el shell 'return' integrado. La sintaxis es la siguiente.

func_name ( ) {
	. . .
	commands
	. . .
	return $ret_val
}

De manera similar, podemos pasar argumentos a las funciones separadas por espacios como se indica a continuación.

func_name $arg_1 $arg_2 $arg_3

Dentro de la función podemos acceder a los argumentos en orden como $1, $2, $3 y así sucesivamente. Mire el siguiente script de ejemplo para encontrar el máximo de dos números enteros usando la función para agregar más claridad.

#!/bin/bash

USG_ERR=7

max_two ( ) {
	if [ "$1" -eq "$2" ] ; then
		echo 'Equal'
		exit 0
	elif [ "$1" -gt "$2" ] ; then
		echo $1
	else
		echo $2
	fi
}

err_str ( ) {
	echo "Usage: $0 <number1>  <number2>"
	exit $USG_ERR
}

NUM_1=$1
NUM_2=$2
x
if [ $# -ne 2 ] ; then
	err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
	if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then  
		max_two $NUM_1 $NUM_2
	else
		err_str
	fi
else
	err_str
fi

exit 0

Lo anterior parece un poco complejo, pero es simple si leemos las líneas. Primero, líneas anidadas if-else if para fines de validación, es decir, para verificar el número y tipo de argumentos con la ayuda de expresiones regulares. Después de eso, llamamos a la función con dos argumentos de línea de comando y mostramos el resultado allí. Esto se debe a que no podemos devolver números enteros grandes de una función. Otra forma de solucionar este problema es utilizar variables globales para almacenar el resultado dentro de la función. El siguiente script explica este método.

#!/bin/bash

USG_ERR=7
ret_val=

max_two ( ) {
	if [ "$1" -eq "$2" ] ; then
		echo 'Equal'
		exit 0
	elif [ "$1" -gt "$2" ] ; then
		ret_val=$1
	else
		ret_val=$2
	fi
}

err_str ( ) {
	echo "Usage: $0 <number1>  <number2>"
	exit $USG_ERR
}

NUM_1=$1
NUM_2=$2

if [ $# -ne 2 ] ; then
	err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
	if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then  
		max_two $NUM_1 $NUM_2
		echo $ret_val
	else
		err_str
	fi
else
	err_str
fi

exit 0

Ahora pruebe algunos problemas interesantes que se explicaron en la serie anterior de secuencias de comandos de shell utilizando las siguientes funciones.

  1. Comprender los consejos básicos del lenguaje de secuencias de comandos Shell de Linux: Parte I
  2. 5 scripts de Shell para que los principiantes de Linux aprendan a programar Shell - Parte II
  3. Navegando por el mundo de las secuencias de comandos BASH de Linux - Parte III
  4. Aspecto matemático de la programación del shell de Linux – Parte IV
  5. Cálculo de expresiones matemáticas en lenguaje de scripting Shell – Parte V

Volveré con más información sobre características funcionales como el uso de variables locales, recursividad, etc. en la siguiente parte. Manténgase actualizado con comentarios.