Aprende GNU/Linux 4

Aprendiendo shell scripting en Linux: Las funciones

Cuando realizamos scripts de pocas o por lo menos no demasiadas lineas, suele ser suficiente con la típica programación estructurada: Empezamos desde arriba y escribimos todas nuestras sentencias hacia abajo hasta que nuestro script termina. Pero cuando el script que estamos programando se complica y empieza a contener demasiadas lineas, y sobre todo cuando alguna tarea del script se realiza dos o más veces, es conveniente utilizar una herramienta que nos evitara repetir lineas de código y nos ayudara a estructurar mejor el script: Las funciones.

¿Que son las funciones?

Las funciones son trozos de código dentro del script, que básicamente, funcionan como un script independiente. En otros lenguajes de programación son denominados como procedimientos o sub-rutinas y su cometido es evitar duplicación de código y dividir un problema en problemas más pequeños, para que sean más fáciles de solucionar, ya sabéis… por eso de: divide y vencerás.

Normalmente las funciones se usan cuando un bloque de código se va a ejecutar varias veces dentro del script, de forma que en vez de duplicar este código a lo largo del script, creamos una función que contendrá este mismo código, y llamaremos a la función cuando sea requerido.

Definición y llamada de las funciones

Las funciones en bash se pueden definir de dos formas, la primera es:

function nombre_función(){
  código_de_la_función
}

y la segunda manera es igual, pero sin la palabra reservada function:

nombre_función(){
  código_de_la_función
}

Para llamar a una función basta con usar su nombre, y si queremos pasar parámetros a una función, los pasaremos después de su nombre:

function nombre_función(){
  código_de_la_función
}

nombre_función $parametro1 $parametro2

Tanto la declaración como la llamada de las funciones no tiene mucho misterio, por lo que la mejor manera de explicar su funcionamiento es mediante ejemplos.

El ejemplo más sencillo: Hola mundo

El ejemplo más sencillo del que podemos hablar es el típico holamundo, sin ningún parámetro:

#! /bin/bash

# Declaramos la función holamundo
function holamundo(){
echo "¡Hola Mundo!"
}
# Llamamos a la función holamundo
holamundo

El resultado del script es:

¡Hola Mundo!

Como vemos la función holamundo contiene una única instrucción, echo. Lo más importante en este ejemplo es comprender el momento de ejecución de este echo: Se ejecuta cuando se realiza la llamada a la función, es decir, en la ultima linea del script.

Añadamos parámetros al asunto

En este segundo ejemplo vamos a utilizar los parámetros, que funcionan de la misma manera que con los bash scripts en general. Se crea una función y con los parámetros de posición ( $1 … $9) podemos hacer referencia a variables que serán enviadas en el momento en el que llamemos a la función:

#! /bin/bash

#Declaramos la función suma
function suma(){
  local a=$1
  local b=$2
  echo $(( $a + $b ))
}
# Llamamos a la función Suma
suma 2 3

En este ejemplo imprimimos  por la salida estándar la suma de dos variables mediante echo. Como se puede observar, dentro de la función creamos dos variables (a y b), les asignamos los valores de los parámetros pasados a la función ( $1 y $2)  y en la tercera linea imprimimos la suma de las dos variables generadas.

Se podría simplificar haciendo echo $(( $1 + $2)), pero de esta manera, podemos observar una declaración de variables exclusiva de las funciones: local.

Cuando declaramos una variable con local, esta pasa a ser exclusiva de la función en la que es creada, por lo que no sera posible utilizarla desde fuera de de la misma función. También es posible crear variables de la manera tradicional, de forma que estas serán utilizables fuera de la función, pero solamente después de llamar a la función en la que se generó la variable.

Valor de retorno

Cuando una función termina su ejecución genera un “estado de salida”, el valor de este estado estará determinado por el ultimo comando de la función: si este se ha ejecutado correctamente el estado de salida tomará el valor cero, sino tomará como valor un error. Este estado se almacena en la variable global: $?, de forma que si queremos acceder a este valor lo haremos mediante esta variable.

Return

Este “estado de salida” en si, no es demasiado útil, pero gracias al comando return podemos hacer que adquiera el valor que necesitemos. La instrucción return puede recibir un argumento como parámetro, de forma que cuando llamemos a return la función terminara su ejecución y el estado de salida tomara el valor de este argumento.

Analicemos el funcionamiento de return con el ejemplo anterior, pero con una pequeña variación:

#! /bin/bash

#Declaramos la función suma
function suma(){
  local a=$1
  local b=$2
  return $(( $a + $b ))
}
# Llamamos a la función Suma
suma 2 3
retorno=$?
echo $retorno

Vemos como la función en vez de realizar un echo, utiliza la instrucción return para devolver la suma de los dos parámetros de posición. Después se ejecuta la función y entonces guardamos el estado de salida en la variable retorno para después imprimirla por la salida estándar mediante echo. El resultado es el mismo que en el ejemplo anterior, es decir: 5.

Recursividad

Entre todas las posibilidades que dan las funciones, una de ellas es la recursividad. Una función recursiva es la que se llama a sí misma dentro de su código, es una técnica que se suele usar para simplificar algoritmos complejos. En este apartado podríamos tirarnos un buen rato, pero no estamos aquí para aprender sobre recursividad, por lo que me voy a limitar a explicar un ejemplo típico de la recursividad: el factorial de un numero.

#!/bin/bash
# Declaramos la función factorial  
function factorial() 
{ 
   if (( $1 < 2 ))
   then
     echo 1
   else
     # Aquí realizamos la recursividad llamando a factorial desde factorial
     echo $(( $1 * $(factorial $(( $1 - 1 ))) ))
   fi
}
# Llamamos a la función 
factorial $1

Como vemos, la función factorial recibe un número y con ese número llama recursivamente otra vez a factorial pero decrementado en uno este número, hasta que llega a uno y termina, volviendo hacia atrás y dando el valor de la recursividad por la salida estándar.

Algunas consideraciones extra

Básicamente las funciones no tienen más, pero evidentemente como en cualquier tipo de programación, podrán adquirir la complejidad que sea necesaria según el problema que necesitemos resolver. Aun así, antes de terminar, quiero hablar de ciertos aspectos de las funciones:

Si se crean dos o más funciones con el mismo nombre, al llamar a la función, se llamará a la última de las funciones declaradas.
No es posible crear una función sin código, por muy absurdo que sea ( error al ejecutar el script)
No se puede llamar a una función antes de definirla.
Las llamadas a funciones son como utilizar un comando más.

Esto es todo respecto a las funciones, si queréis aprender más sobre la terminal y los scripts aquí tenéis todos los artículos escritos hasta la fecha sobre el tema:

Sobre el autor / 

AsierPH

Entusiasta de las tecnologías libres y fundador de OvToaster.com | “Las obras de conocimiento deben ser libres, no hay excusas para que no sea así“

Articulos relacionados

4 comentarios

  1. wsn 27 Agosto, 2015 at 10:03 am -  Responder

    Valla!, esta web es como una mina de oro y diamantes!

    Al menos para mi que hace poco he dado el salto definitivo a GNU/Linux. Así da gusto aprender, con estos artículos tan bien explicados.

    Saludos!

    • AsierPH 27 Agosto, 2015 at 10:18 am -  Responder

      Hola de nuevo Wsn
      Muchas gracias por tus comentarios, ayudan mucho a continuar creando contenido, y me alegro de tu salto a GNU/Linux 🙂
      ¡Un saludo!

  2. willarmand 11 Febrero, 2015 at 6:58 am -  Responder

    Saludos AsierPh
    Muy instructivo, es como reaprender las matematicas, je je je
    Para mi es un misterio de donde salen los comandos, y ademas, por ejemplo un comando que se pondria en la terminal, ya puesto en un script veo que se desglosa por decirlo asi.
    Y tambien hay alguna manera de resolver ese misterio, para mi, de los comandos, es decir, su origen ?
    Por cierto, muchas gracias por tu respuesta acerca del cron, no se si recibiste otra duda al respecto por correo.
    Saludos

    • AsierPH 11 Febrero, 2015 at 11:25 am -  Responder

      Hola Willarmand
      Gracias por el comentario, estos interpretes son muy antiguos y normalmente se basan en otros anteriores. En el caso de Bash fue creado para el proyecto GNU y se basa en el interprete shell Bourne que fue creado para Unix.
      Si que he leído tu e-mail, pero dame esta semana para responderte adecuadamente porque ando ocupadillo, pero tranquilo que no me olvido 🙂
      ¡Un saludo!

Deja tu comentario

Tu correo no sera publicado. Los campos requeridos están marcados *