Declaración y Uso de Funciones

Construye código modular y reutilizable con funciones

Módulo 4 ⏱️ 40-45 min 🧩 Funciones 🏗️ Modularidad 📚 Intermedio

¿Qué son las Funciones?

Las funciones en Bash son bloques de código reutilizable que encapsulan una tarea específica. Permiten organizar el código en unidades lógicas, evitar la repetición y crear scripts más mantenibles y legibles.

Una función es como una mini-programa dentro de tu script que puede recibir parámetros, procesar información y devolver resultados. Una vez definida, puedes llamarla tantas veces como necesites.

Reutilización

Escribe una vez, usa muchas veces. Las funciones eliminan la duplicación de código.

Modularidad

Divide problemas complejos en partes más pequeñas y manejables.

Mantenimiento

Cambios en una función se reflejan automáticamente en todos los lugares donde se usa.

Legibilidad

El código se vuelve más fácil de leer y entender cuando está bien organizado.

Sintaxis de Declaración

Bash ofrece dos sintaxis principales para declarar funciones. Ambas son equivalentes en funcionalidad:

Sintaxis de Funciones

Sintaxis Tradicional
Forma tradicional (recomendada) Copiar
nombre_funcion() {
    # código de la función
    echo "Hola desde la función"
    return 0  # opcional
}
Sintaxis con Palabra Clave
Con palabra clave function Copiar
function nombre_funcion {
    # código de la función
    echo "Hola desde la función"
    return 0  # opcional
}
Recomendación

Usa la sintaxis tradicional con paréntesis nombre_funcion() { } ya que es más portable y ampliamente reconocida en la comunidad Bash.

Anatomía de una Función

Componentes de una Función

1
Nombre de la función: Identificador único que usarás para llamar la función. Debe seguir las reglas de nombres de variables.
2
Paréntesis (): Indican que es una función. No se ponen parámetros aquí (a diferencia de otros lenguajes).
3
Llaves { }: Delimitan el cuerpo de la función. La llave de apertura puede ir en la misma línea o en una nueva línea.
4
Cuerpo de la función: Contiene los comandos que se ejecutarán cuando se llame la función.
5
Return (opcional): Define el código de salida de la función (0-255). Si no se especifica, devuelve el estado del último comando.
Ejemplo detallado Copiar
#!/bin/bash
# Función que saluda con información del sistema
saludar_sistema() {                    # ← 1. Nombre de función
    echo "¡Hola desde el sistema!"     # ← 4. Cuerpo de la función
    echo "Usuario actual: $(whoami)"
    echo "Fecha: $(date)"
    echo "Directorio: $(pwd)"
    return 0                           # ← 5. Código de retorno
}                                      # ← 3. Llave de cierre

Llamada de Funciones

Para usar una función, simplemente escribe su nombre. La función debe estar definida antes de ser llamada.

Ejemplo básico de función y llamada Copiar
#!/bin/bash

# 1. Definir la función
mostrar_menu() {
    echo "================================"
    echo "    MENÚ PRINCIPAL"
    echo "================================"
    echo "1. Ver archivos"
    echo "2. Ver procesos"
    echo "3. Ver información del sistema"
    echo "4. Salir"
    echo "================================"
}

# 2. Llamar la función
echo "Bienvenido al sistema"
mostrar_menu

echo ""
echo "Función llamada exitosamente"
$ ./mi_script.sh
Bienvenido al sistema
================================
    MENÚ PRINCIPAL
================================
1. Ver archivos
2. Ver procesos
3. Ver información del sistema
4. Salir
================================

Función llamada exitosamente

Valores de Retorno

Las funciones en Bash pueden devolver un código de estado (0-255) usando return. También pueden "devolver" datos imprimiendo al stdout, que luego puedes capturar.

1. Códigos de Retorno

Función con códigos de retorno Copiar
#!/bin/bash

# Función que verifica si un archivo existe
verificar_archivo() {
    local archivo="$1"
    
    if [ -f "$archivo" ]; then
        echo "El archivo $archivo existe"
        return 0    # Éxito
    else
        echo "El archivo $archivo NO existe"
        return 1    # Error
    fi
}

# Usar la función y verificar el resultado
verificar_archivo "/etc/passwd"
if [ $? -eq 0 ]; then
    echo "✓ Verificación exitosa"
else
    echo "✗ Error en la verificación"
fi

echo ""

verificar_archivo "/archivo/inexistente.txt"
if [ $? -eq 0 ]; then
    echo "✓ Verificación exitosa"
else
    echo "✗ Error en la verificación"
fi

2. Devolver Datos via Stdout

Función que "devuelve" datos Copiar
#!/bin/bash

# Función que calcula el cuadrado de un número
calcular_cuadrado() {
    local numero=$1
    local resultado=$((numero * numero))
    echo $resultado  # "Devolver" el resultado
}

# Función que obtiene información del sistema
obtener_info_sistema() {
    echo "$(uname -s)|$(whoami)|$(date +%Y-%m-%d)"
}

# Capturar los resultados
echo "Calculando cuadrados:"
cuadrado_5=$(calcular_cuadrado 5)
cuadrado_12=$(calcular_cuadrado 12)

echo "5² = $cuadrado_5"
echo "12² = $cuadrado_12"

echo ""
echo "Información del sistema:"
info=$(obtener_info_sistema)
IFS='|' read -r sistema usuario fecha <<< "$info"
echo "Sistema: $sistema"
echo "Usuario: $usuario"  
echo "Fecha: $fecha"
$ ./calcular.sh
Calculando cuadrados:
5² = 25
12² = 144

Información del sistema:
Sistema: Linux
Usuario: usuario
Fecha: 2024-01-15
Importante sobre Return

El comando return solo puede devolver números entre 0 y 255. Para devolver texto o datos complejos, usa echo y captura la salida con $().

Ejemplos Prácticos

Utilidades de Archivos
Funciones para manejo de archivos Copiar
#!/bin/bash

# Función para crear backup de un archivo
crear_backup() {
    local archivo="$1"
    local fecha=$(date +%Y%m%d_%H%M%S)
    local backup="${archivo}.backup_${fecha}"
    
    if [ -f "$archivo" ]; then
        cp "$archivo" "$backup"
        echo "Backup creado: $backup"
        return 0
    else
        echo "Error: Archivo $archivo no existe"
        return 1
    fi
}

# Función para obtener el tamaño de un archivo en formato legible
obtener_tamaño() {
    local archivo="$1"
    
    if [ -f "$archivo" ]; then
        if command -v du &> /dev/null; then
            du -h "$archivo" | cut -f1
        else
            ls -lh "$archivo" | awk '{print $5}'
        fi
    else
        echo "N/A"
    fi
}

# Función para limpiar archivos temporales
limpiar_temporales() {
    local directorio="${1:-.}"
    local archivos_eliminados=0
    
    for archivo in "$directorio"/*.tmp "$directorio"/*.temp
    do
        if [ -f "$archivo" ]; then
            rm "$archivo"
            echo "Eliminado: $(basename $archivo)"
            ((archivos_eliminados++))
        fi
    done
    
    echo "Total archivos eliminados: $archivos_eliminados"
    return 0
}

# Ejemplo de uso
echo "=== Utilidades de Archivos ==="
crear_backup "/etc/hosts"
echo "Tamaño de /etc/passwd: $(obtener_tamaño /etc/passwd)"
limpiar_temporales /tmp
Utilidades de Sistema
Funciones de monitoreo Copiar
#!/bin/bash

# Función para verificar si un servicio está corriendo
verificar_servicio() {
    local servicio="$1"
    
    if systemctl is-active --quiet "$servicio"; then
        echo "✓ $servicio está corriendo"
        return 0
    else
        echo "✗ $servicio no está corriendo"
        return 1
    fi
}

# Función para obtener uso de memoria
obtener_memoria() {
    local tipo="${1:-porcentaje}"
    
    case $tipo in
        "porcentaje")
            free | grep Mem | awk '{printf("%.1f%%\n", ($3/$2)*100)}'
            ;;
        "usado")
            free -h | grep Mem | awk '{print $3}'
            ;;
        "total")
            free -h | grep Mem | awk '{print $2}'
            ;;
        *)
            echo "Opciones: porcentaje, usado, total"
            return 1
            ;;
    esac
}

# Función para verificar espacio en disco
verificar_espacio() {
    local punto_montaje="${1:-/}"
    local umbral="${2:-90}"
    
    local uso=$(df "$punto_montaje" | tail -1 | awk '{print $5}' | sed 's/%//')
    
    if [ "$uso" -gt "$umbral" ]; then
        echo "⚠️  ALERTA: Espacio en disco al $uso% en $punto_montaje"
        return 1
    else
        echo "✓ Espacio en disco OK: $uso% en $punto_montaje"
        return 0
    fi
}

# Ejemplo de uso
echo "=== Monitor de Sistema ==="
verificar_servicio "ssh"
echo "Memoria usada: $(obtener_memoria usado) de $(obtener_memoria total)"
echo "Uso de memoria: $(obtener_memoria porcentaje)"
verificar_espacio "/" 80

Ejercicios Prácticos

Ejercicio 1: Calculadora de Funciones

Crea un conjunto de funciones matemáticas básicas:

calculadora.sh Copiar
#!/bin/bash
# Calculadora básica con funciones

# Función para sumar
sumar() {
    local a=$1
    local b=$2
    echo $((a + b))
}

# Función para restar
restar() {
    local a=$1
    local b=$2
    echo $((a - b))
}

# Función para multiplicar
multiplicar() {
    local a=$1
    local b=$2
    echo $((a * b))
}

# Función para dividir
dividir() {
    local a=$1
    local b=$2
    
    if [ "$b" -eq 0 ]; then
        echo "Error: División por cero"
        return 1
    fi
    
    # Usar bc para división con decimales si está disponible
    if command -v bc &> /dev/null; then
        echo "scale=2; $a / $b" | bc
    else
        echo $((a / b))
    fi
}

# Función para calcular potencia
potencia() {
    local base=$1
    local exponente=$2
    local resultado=1
    
    for ((i=1; i<=exponente; i++)); do
        resultado=$((resultado * base))
    done
    
    echo $resultado
}

# Función principal del menú
mostrar_menu() {
    echo "================================="
    echo "    CALCULADORA BASH"
    echo "================================="
    echo "1. Sumar"
    echo "2. Restar"
    echo "3. Multiplicar"
    echo "4. Dividir"
    echo "5. Potencia"
    echo "6. Salir"
    echo "================================="
}

# Programa principal
while true; do
    mostrar_menu
    read -p "Selecciona una opción: " opcion
    
    case $opcion in
        1|2|3|4|5)
            read -p "Ingresa el primer número: " num1
            read -p "Ingresa el segundo número: " num2
            
            case $opcion in
                1) echo "Resultado: $(sumar $num1 $num2)" ;;
                2) echo "Resultado: $(restar $num1 $num2)" ;;
                3) echo "Resultado: $(multiplicar $num1 $num2)" ;;
                4) dividir $num1 $num2 ;;
                5) echo "Resultado: $(potencia $num1 $num2)" ;;
            esac
            ;;
        6)
            echo "¡Hasta luego!"
            exit 0
            ;;
        *)
            echo "Opción no válida"
            ;;
    esac
    
    echo ""
    read -p "Presiona Enter para continuar..."
    clear
done
Ejercicio 2: Gestor de Logs

Crea un sistema de funciones para manejar archivos de log:

gestor_logs.sh Copiar
#!/bin/bash
# Gestor de logs con funciones

LOG_DIR="/var/log"
LOG_FILE="aplicacion.log"

# Función para escribir entrada de log
escribir_log() {
    local nivel="$1"
    local mensaje="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    echo "[$timestamp] [$nivel] $mensaje" >> "$LOG_FILE"
}

# Funciones específicas para cada nivel
log_info() {
    escribir_log "INFO" "$1"
    echo "ℹ️  INFO: $1"
}

log_warning() {
    escribir_log "WARNING" "$1"
    echo "⚠️  WARNING: $1"
}

log_error() {
    escribir_log "ERROR" "$1"
    echo "❌ ERROR: $1"
}

log_debug() {
    escribir_log "DEBUG" "$1"
    echo "🐛 DEBUG: $1"
}

# Función para rotar logs
rotar_logs() {
    if [ -f "$LOG_FILE" ]; then
        local backup="${LOG_FILE}.$(date +%Y%m%d_%H%M%S)"
        mv "$LOG_FILE" "$backup"
        echo "Log rotado a: $backup"
        touch "$LOG_FILE"
    else
        echo "No hay archivo de log para rotar"
    fi
}

# Función para leer últimas entradas
leer_ultimos_logs() {
    local cantidad="${1:-10}"
    
    if [ -f "$LOG_FILE" ]; then
        echo "Últimas $cantidad entradas del log:"
        echo "=================================="
        tail -n "$cantidad" "$LOG_FILE"
    else
        echo "No existe el archivo de log: $LOG_FILE"
    fi
}

# Función para buscar en logs
buscar_en_logs() {
    local patron="$1"
    
    if [ -f "$LOG_FILE" ]; then
        echo "Buscando '$patron' en los logs:"
        echo "================================"
        grep -n "$patron" "$LOG_FILE"
    else
        echo "No existe el archivo de log: $LOG_FILE"
    fi
}

# Función para estadísticas de logs
estadisticas_logs() {
    if [ -f "$LOG_FILE" ]; then
        echo "Estadísticas del log:"
        echo "===================="
        echo "Total de líneas: $(wc -l < "$LOG_FILE")"
        echo "Entradas INFO: $(grep -c "INFO" "$LOG_FILE")"
        echo "Entradas WARNING: $(grep -c "WARNING" "$LOG_FILE")"
        echo "Entradas ERROR: $(grep -c "ERROR" "$LOG_FILE")"
        echo "Entradas DEBUG: $(grep -c "DEBUG" "$LOG_FILE")"
    else
        echo "No existe el archivo de log: $LOG_FILE"
    fi
}

# Ejemplos de uso
echo "=== Gestor de Logs ==="

# Escribir algunos logs de ejemplo
log_info "Aplicación iniciada"
log_info "Conectando a la base de datos"
log_warning "Conexión lenta detectada"
log_error "Error al conectar con el servidor"
log_debug "Variable DEBUG_MODE=true"

echo ""
estadisticas_logs

echo ""
leer_ultimos_logs 3