.. _sh-func: Funciones ========= La *shell* permite definir *funciones* con la siguiente sintaxis: .. code-block:: bash nombre_funcion() { # Bloque de órdenes que la componen } .. note:: Dado que el código es interpretado línea a línea, la definición de la función debe encontrarse antes de su primera invocación. Como puede verse, sólo se declara la función y no los argumentos que recibe. El bloque de órdenes tiene las siguientes particularidades: #. Las funciones se invocan de la misma manera que las órdenes:: nombre_funcion uno dos tres de manera que "*uno*", "*dos*" y "*tres*" son los tres argumentos que se le proporcionan. #. Los argumentos proporcionados a la función son accesibles mediante las variables ``$1``, ``$2``, etc., es decir, exactamente igual que son accesibles los argumentos del *script* en el código principal. Todo lo dicho para estos argumentos es aplicable a los argumentos de la función. #. Dentro de la función son accesibles las variables globales, esto es, las existentes en el código principal del *script* (excepto las referentes a los argumentos del *script*, porque se sobreescriben con los valores de los argumentos de la propia función). Si se asigna valor a alguna de estas variables, el valor se propagará fuera de la función. #. Si se define una variable dentro de la función tal como hemos ya explicado, la *variable* será global. Para que sea local a la función hay que definirla usando la :index:`palabra ` :command:`local`:: local soy_local .. note:: Con :command:`local` pueden usarse las mismas opciones que con :command:`declare`. Por ejemplo, ``-a`` para definir un vector. .. warning:: :command:`local` no forma parte del estándar POSIX\ [#]_, pero la mayoría de las *shells* (con la excepción de :command:`ksh`\ [#]_, pero no ide su derivada :command:`mksh`) lo implementan. #. Vista desde fuera (o sea, vista desde el código que la invoca), una función podemos considerarla casi a todos los efectos como una orden [interna]\ [#]_, por lo que: * Puede participar en tuberías: .. code-block:: bash toupper() { tr '[:lower:]' '[:upper:]' } echo "Pása a mayúsculas" | toupper * Envía datos al resto del código imprimiendo en pantalla. El ejemplo escrito arriba lo ilustra: el resultado, simplemente, se manda a pantalla. Si hubiéramos querido capturarlo, habríamos hecho lo mismo que cuando capturamos salidas de órdenes:: traduccion=$(echo "Pása a mayúsculas" | toupper) * Es capaz de devolver el buen o mal suceso de la tarea que desarrolla mediante un *byte*. Esta devolución se hace con la palabra :command:`return`, en vez de :command:`exit`, ya que esta última provocaría la salida inmediata del proceso, no de la función. Como en el caso del programa, si explícitamente no se usa :command:`return`, el código de salida es el código de salida de la última instrucción que se ejecutó. En el código principal, su código de salida se asigna a la variable ``$?``, exactamente igual que cuando se ejecuta una orden. .. warning:: Es importante tener presente esto: las funciones de la *shell* no son capaces de devolver datos: sólo código de sálida, por lo que cualquier dato que se desee exportar se ha de hacer a través de la pantalla (o de un fichero, claro). .. note:: Revise el :ref:`apartado dedicado al valor de retorno `. #. Si se definen dos funciones con un mismo nombre, prevalece la última definición. #. Podemos anidar funciones, esto es, definir una función dentro de otra función. Si hacemos así, la función interna sólo será accesible desde la externa. Cuando tratamos la orden interna :ref:`alias `, vimos que podía usarse la barra invertida o la orden interna :ref:`command ` para evitar la ejecución del alias. Esto permitía modificar el comportamiento normal de una órden escribiendo un alias homónimo: .. code-block:: bash alias ls='ls --color=auto -F' Pues bien, ambas alternativas también evitan la ejecución de funciones, por lo que es posible escribir *wrappers* también con funciones: .. code-block:: bash ls() { command ls -F --color=auto "$@" } .. note:: Con independencia de que en este caso tan simple es mejor hacer el *wrapper* con :command:`alias`, observe una sutil diferencia entre ambos: la definición de :command:`alias` entiende :command:`ls` como el comando a secas, mientras que al ejecutarse la función, :command:`ls` se tomará como su definición en ese momento, que es la propia función, por lo que se obtendría una recursión infinita si no usáramos :command:`command`. .. rubric:: Ejemplo *Definir una función que calcule la clase a la que pertenece una IP determinada* .. code-block:: bash #!/bin/sh # Determina si una IP es correcta # $1: La IP es_ip() { # En realidad sólo comprobamos si hay # cuatro números separados por 3 puntos. echo "$1" | grep -Eq '^[0-9]+(\.[0-9]){3}$' } # Calcula la clase de red. # Parámetros: # $1: La IP. # Devuelve error si la IP es incorrecta. netclass() { es_ip $1 || return 1 local octeto=${1%%.*} if [ $octeto -lt 128 ]; then echo "A" elif [ $octeto -lt 192 ]; then echo "B" elif [ $octeto -lt 224 ]; then echo "C" elif [ $octeto -lt 240 ]; then echo "D" else echo "E" fi } clase=$(netclass $1) res=$? if [ $res -ne 0 ]; then echo "Imposible obtener la clase de $1" >&2 exit $res fi echo "La clase de $1 es $clase." El código de ejemplo no tiene mucho misterio: nos quedamos sólo con el primer byte , comprobamos que es un número y, después, dependiendo de cuál sea, imprimimos por pantalla su clase. En un lenguaje de programación normal, la letra que identifica la clase sería el valor de retorno, pero en la *shell* esto no puede ser así: el valor de retorno tiene forzosamente que ser un byte y sólo sirve para indicar al código invocante si se ha podido realizar el cálculo o no. Por esa razón, devolvemos valores distintos de cero al producirse errores. Cuando estos no se producen, se devuelve la valor de retorno de la última orden, que es :command:`echo` y no falla nunca. Obsérvese también cómo podemos usar la función para retener la clase: con una subshell que captura la salida. Después no tenemos más que comprobar el valor de retorno para ver si se produjo o no error; y en caso de que no, continuar nuestro programa sabiendo que tenemos el cálculo almacenado en la variable ``clase``. .. rubric:: Notas al pie .. [#] De hecho, con el estándar *POSIX* no hay forma de definir variables locales. .. [#] :command:`ksh` utiliza un método totalmente distinto para definir variables locales a la función: obliga a definir la función con otra sintaxis (:code:`function nombre_funcion { ... }`) y a anteponer la palabra reservada *typeset* en la declaración de la variable. .. [#] Hay una notabilísima excepción, muy natural por lo demás: los programas externos que sirven para invocar a otros programas son incapaces de invocar funciones, porque estas son internas a la *shell*. Por ese motivo, funciona:: $ time sleep 3 real 0m3,002s user 0m0,001s sys 0m0,001s pero jamás funcionaría para saber cuánto tarda en ejecutarse una función. Otra utilidad de este tipo es la :ref:`ya vista xargs `. .. seealso:: Éche un ojo a :ref:`cómo poder usar funciones en órdenes externas `.