Funciones en Shell Script
En Shell Script, como en prácticamente todos los lenguajes de programación, podemos empaquetar conjuntos de instrucciones en funciones. Cada función tiene un nombre gracias al cual, podemos invocar a esa función tantas veces como necesitemos realizar esas instrucciones únicamente con escribir el nombre de la función.
Una función, como otros bloques de código se divide en tres partes, que pueden existir en esa función o no:
- Entrada de datos
- Proceso de datos
- Retorno de datos
Funciones sin entrada de datos
Para definir una función tenemos dos opciones, escribiendo function antes del nombre de la función o directamente escribiendo el nombre de la función seguido de paréntesis y el código de la función entre llaves.
Vamos a ver dos funciones básicas sin entrada de datos. Una definida con la palabra reservada function y otra sin la palabra reservada function:
#!/bin/bash function hola(){ echo Hola, mundo, desde la función hola. } saludo(){ echo Hola, mundo, desde la función saludo. } hola saludo
El resultado generado al ejecutar es:
Hola, mundo, desde la función hola. Hola, mundo, desde la función saludo.
De este ejemplo podemos sacar dos conclusiones:
Es indiferente a la hora de definir la función usar o no usar la palabra function.
Una función a la que no le enviamos parámetros ni devuelve ningún resultado, se invoca escribiendo su nombre.
Funciones con entrada de datos
Ahora pasemos a las funciones con entrada de datos que, a diferencia de otros lenguajes de programación, Shell Script no necesita que se las indiquemos a la hora de declarar la función, sino que recibe todas las que le enviemos y las almacena en una serie de variables especiales, al estilo de los parámetros de un script.
Modifiquemos el ejemplo anterior para indicarle a quién debe saludar en lugar del genérico «mundo»:
#!/bin/bash function hola(){ echo Hola, $1, desde la función hola. } saludo(){ echo Hola, $1, desde la función saludo. } hola Pepe saludo Juan
que devuelve:
Hola, Pepe, desde la función hola. Hola, Juan, desde la función saludo.
De donde extraemos que si queremos enviar parámetros a una función que no devuelve un resultado, podemos hacerlo como un comando, es decir:
nombre_de_la_funcion parametro_1 parametro_2 parametro_3 [...]
Y que, al recibir los parámetros en la función, los numera por orden de cómo los recibe. Pero con una característica especial. Veamos qué ocurre si usamos la variable $0:
#!/bin/bash function numeracion_parametros(){ echo Parámetro 0: $0 } numeracion_parametros
Que, en mi caso, me devuelve:
Parámetro 0: ./funciones.sh
Con $0 dentro de una función no devuelve el nombre de la función, sino el nombre del script.
Veamos cómo cambia el uso de $0 y $1 en un script y en una función. Escribimos el código:
#!/bin/bash function numeracion_parametros(){ echo Parámetro 0: $0 dentro de la función. echo Parámetro 1: $1 dentro de la función. } echo Parámetro 0: $0 fuera de la función. echo Parámetro 1: $1 fuera de la función. numeracion_parametros función
Y lo ejecutamos:
$ ./funciones.sh script Parámetro 0: ./funciones.sh fuera de la función. Parámetro 1: script fuera de la función. Parámetro 0: ./funciones.sh dentro de la función. Parámetro 1: función dentro de la función.
Como vemos, $0 es igual dentro y fuera de la función (nombre del script) y $1 cambia, siendo el primer parámetro del script o de la función según dónde se le invoque.
Una duda muy habitual es cómo invocar a las variables mayores de 9 sin generar conflicto con las que únicamente tienen un dígito. Símplemente hay que expandir con ${}. Así:
#!/bin/bash function numeracion_parametros(){ echo Parámetro 1: $1 echo Parámetro 10: ${10} } numeracion_parametros En un lugar de la Mancha, de cuyo nombre no quiero acordarme
Que devuelve:
Parámetro 1: En Parámetro 10: no
Como en los argumentos de un script, el número de parámetros recibidos lo podemos saber con $# y la lista de argumentos con $@ o con $*. Vamos a mostrar el número de argumentos:
#!/bin/bash function numeracion_parametros(){ echo Número de parámetros: $# } numeracion_parametros En un lugar de la Mancha, de cuyo nombre no quiero acordarme
que nos indica:
Número de parámetros: 12
Y los podemos listar o recorrer:
#!/bin/bash function numeracion_parametros(){ echo Número de parámetros: $# echo Los listo: $@ echo Y los recorro: for i in "$@" do echo $i done } numeracion_parametros En un lugar de la Mancha, de cuyo nombre no quiero acordarme
que nos devuelve:
Número de parámetros: 12 Los listo: En un lugar de la Mancha, de cuyo nombre no quiero acordarme Y los recorro: En un lugar de la Mancha, de cuyo nombre no quiero acordarme
Retorno de valores
Por último vamos a ver cómo devolver valores desde una función. Para devolver esos valores usaremos el comando echo igual que si fuésemos a imprimir por pantalla, pero al invocar la función, vamos a hacer una sustitución de comandos con $() para ejecutar la función en una subcapa y almacenar la salida en una variable.
Podemos usar esta fórmula indicando parámetros a la función:
#!/bin/bash function addition() { result=0 for i in $@ do let result=$result+$i done echo $result } total=$(addition 1 2 3 4) echo $total
O sin pasarle parámetros a la función:
#!/bin/bash function happyday(){ echo "#Feliz"$(date +%A) } hashtag=$(happyday) echo $hashtag