Sentencias Case

Crea menús elegantes y lógica condicional eficiente con case

Módulo 3 ⏱️ 25-30 min 🎯 Menús ⚡ Case 📚 Principiante

¿Qué es la Sentencia Case?

La sentencia case es una alternativa elegante y eficiente a las múltiples sentencias if-elif-else. Es especialmente útil cuando necesitas comparar una variable contra múltiples valores posibles, como en la creación de menús o el procesamiento de opciones.

A diferencia de if-elif, que puede evaluar expresiones complejas, case solo puede comparar patrones contra el valor de una variable, pero lo hace de manera más eficiente y legible.

Estructura General de Case
case $variable in

patrón1)
comandos_para_patrón1
;;
patrón2 | patrón3)
comandos_para_patrón2_o_3
;;
*)
comandos_por_defecto
;;
esac
Elementos Clave
  • case: Palabra clave que inicia la estructura
  • $variable: La variable que se va a comparar
  • patrón): Los patrones a comparar (terminan con )
  • ;; Termina cada bloque de comandos
  • *): Patrón por defecto (catch-all)
  • esac: Termina la estructura (case al revés)

Ejemplo Básico de Case

# Ejemplo básico: menú de opciones
$ cat > menu_basico.sh << 'EOF'
#!/bin/bash

echo "=== Menú Principal ==="
echo "1) Ver archivos"
echo "2) Ver procesos"
echo "3) Ver información del sistema"
echo "4) Salir"
echo
echo "Selecciona una opción (1-4):"
read opcion

case $opcion in
    1)
        echo "📁 Listando archivos:"
        ls -la
        ;;
    2)
        echo "⚙️  Procesos activos:"
        ps aux | head -10
        ;;
    3)
        echo "💻 Información del sistema:"
        uname -a
        uptime
        ;;
    4)
        echo "👋 ¡Hasta luego!"
        exit 0
        ;;
    *)
        echo "❌ Opción inválida. Usa 1-4."
        ;;
esac
EOF

$ chmod +x menu_basico.sh
$ ./menu_basico.sh
=== Menú Principal ===
1) Ver archivos
2) Ver procesos
3) Ver información del sistema
4) Salir

Selecciona una opción (1-4):
1
📁 Listando archivos:
total 8
-rwxr-xr-x 1 user user 456 oct 15 12:00 menu_basico.sh
Case vs If-Elif

El ejemplo anterior con if-elif sería más verbose:

if [[ $opcion -eq 1 ]]; then
    # comandos
elif [[ $opcion -eq 2 ]]; then
    # comandos
elif [[ $opcion -eq 3 ]]; then
    # comandos
# ... etc

Patrones en Case

Los patrones en case son muy flexibles y soportan wildcards, rangos, y múltiples opciones. Esto los hace extremadamente poderosos para matching complejo.

Patrón Descripción Ejemplo Coincide con
literal Coincidencia exacta yes) Exactamente "yes"
* Cualquier cadena *) Todo (caso por defecto)
? Un solo carácter ?) Cualquier carácter único
[abc] Cualquiera de los caracteres [yYsS]) y, Y, s, o S
[a-z] Rango de caracteres [0-9]) Cualquier dígito
a|b Alternativas múltiples yes|y|YES) yes, y, o YES
*.txt Termina con patrón *.log) Archivos .log
pre* Empieza con patrón test*) Empieza con "test"
# Ejemplo avanzado con patrones
$ cat > patrones_case.sh << 'EOF'
#!/bin/bash

echo "Introduce un comando, archivo o respuesta:"
read input

case $input in
    # Comandos específicos
    ls|dir)
        echo "🔍 Listando contenido del directorio"
        ls -la
        ;;
    
    # Archivos por extensión
    *.txt|*.log)
        echo "📄 Archivo de texto detectado: $input"
        if [[ -f "$input" ]]; then
            echo "Mostrando primeras líneas:"
            head -5 "$input"
        else
            echo "El archivo no existe"
        fi
        ;;
    
    *.sh)
        echo "🔧 Script de Bash detectado: $input"
        if [[ -f "$input" ]]; then
            echo "¿Quieres ejecutarlo? (s/n)"
            read ejecutar
            case $ejecutar in
                s|S|yes|YES|y|Y)
                    echo "Ejecutando $input..."
                    bash "$input"
                    ;;
                *)
                    echo "Script no ejecutado"
                    ;;
            esac
        fi
        ;;
    
    # Respuestas afirmativas
    [yY]|[yY][eE][sS]|[sS]|[sS][íiÍI])
        echo "✅ Respuesta afirmativa recibida"
        ;;
    
    # Respuestas negativas
    [nN]|[nN][oO]|[nN][oO][nN])
        echo "❌ Respuesta negativa recibida"
        ;;
    
    # Números
    [0-9])
        echo "🔢 Dígito único: $input"
        ;;
    
    [0-9][0-9])
        echo "🔢 Número de dos dígitos: $input"
        ;;
    
    # URLs
    http://*|https://*)
        echo "🌐 URL detectada: $input"
        echo "¿Abrir en navegador? (s/n)"
        ;;
    
    # Caso por defecto
    *)
        echo "🤷 No reconozco ese patrón: $input"
        echo "Tipo: $(file "$input" 2>/dev/null || echo "desconocido")"
        ;;
esac
EOF

$ chmod +x patrones_case.sh
$ ./patrones_case.sh
Introduce un comando, archivo o respuesta:
test.sh
🔧 Script de Bash detectado: test.sh

Menús Interactivos Avanzados

Sistema de menús profesional Copiar
#!/bin/bash
# Sistema de menús profesional con submenús

# Colores para mejorar la presentación
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Función para mostrar el menú principal
mostrar_menu_principal() {
    clear
    echo -e "${BLUE}╔══════════════════════════════════╗${NC}"
    echo -e "${BLUE}║     🖥️  ADMINISTRADOR SISTEMA    ║${NC}"
    echo -e "${BLUE}╚══════════════════════════════════╝${NC}"
    echo
    echo -e "${CYAN}1)${NC} 📁 Gestión de Archivos"
    echo -e "${CYAN}2)${NC} ⚙️  Gestión de Procesos"
    echo -e "${CYAN}3)${NC} 🌐 Gestión de Red"
    echo -e "${CYAN}4)${NC} 👥 Gestión de Usuarios"
    echo -e "${CYAN}5)${NC} 📊 Información del Sistema"
    echo -e "${CYAN}6)${NC} 🛠️  Herramientas de Mantenimiento"
    echo -e "${CYAN}0)${NC} 🚪 Salir"
    echo
    echo -ne "${YELLOW}Selecciona una opción: ${NC}"
}

# Función para gestión de archivos
menu_archivos() {
    while true; do
        clear
        echo -e "${GREEN}═══ GESTIÓN DE ARCHIVOS ═══${NC}"
        echo
        echo "1) Listar archivos detallado"
        echo "2) Buscar archivos"
        echo "3) Comprimir directorio"
        echo "4) Permisos de archivos"
        echo "0) Volver al menú principal"
        echo
        echo -ne "Opción: "
        read opcion
        
        case $opcion in
            1)
                echo -e "\n${BLUE}📁 Listado detallado:${NC}"
                ls -lah --color=always
                read -p "Presiona Enter para continuar..."
                ;;
            2)
                echo -ne "\n🔍 Buscar archivo (nombre): "
                read archivo
                echo -e "\n${BLUE}Resultados:${NC}"
                find . -name "*$archivo*" -type f 2>/dev/null | head -20
                read -p "Presiona Enter para continuar..."
                ;;
            3)
                echo -ne "\n📦 Directorio a comprimir: "
                read directorio
                if [[ -d "$directorio" ]]; then
                    tar_name="${directorio}_$(date +%Y%m%d_%H%M).tar.gz"
                    echo "Comprimiendo a $tar_name..."
                    tar -czf "$tar_name" "$directorio"
                    echo -e "${GREEN}✅ Completado${NC}"
                else
                    echo -e "${RED}❌ Directorio no encontrado${NC}"
                fi
                read -p "Presiona Enter para continuar..."
                ;;
            4)
                echo -ne "\n🔒 Archivo para ver permisos: "
                read archivo
                if [[ -e "$archivo" ]]; then
                    echo -e "\n${BLUE}Información de permisos:${NC}"
                    ls -la "$archivo"
                    stat "$archivo"
                else
                    echo -e "${RED}❌ Archivo no encontrado${NC}"
                fi
                read -p "Presiona Enter para continuar..."
                ;;
            0)
                break
                ;;
            *)
                echo -e "${RED}❌ Opción inválida${NC}"
                sleep 1
                ;;
        esac
    done
}

# Función para gestión de procesos
menu_procesos() {
    while true; do
        clear
        echo -e "${GREEN}═══ GESTIÓN DE PROCESOS ═══${NC}"
        echo
        echo "1) Procesos activos (top 10)"
        echo "2) Procesos por usuario"
        echo "3) Buscar proceso"
        echo "4) Matar proceso"
        echo "5) Monitoreo en tiempo real"
        echo "0) Volver al menú principal"
        echo
        echo -ne "Opción: "
        read opcion
        
        case $opcion in
            1)
                echo -e "\n${BLUE}⚙️ Top 10 procesos por CPU:${NC}"
                ps aux --sort=-%cpu | head -11
                read -p "Presiona Enter para continuar..."
                ;;
            2)
                echo -ne "\n👤 Usuario: "
                read usuario
                echo -e "\n${BLUE}Procesos de $usuario:${NC}"
                ps -u "$usuario" 2>/dev/null || echo -e "${RED}Usuario no encontrado${NC}"
                read -p "Presiona Enter para continuar..."
                ;;
            3)
                echo -ne "\n🔍 Buscar proceso: "
                read proceso
                echo -e "\n${BLUE}Resultados:${NC}"
                pgrep -f "$proceso" | xargs ps -p 2>/dev/null || echo "No encontrado"
                read -p "Presiona Enter para continuar..."
                ;;
            4)
                echo -ne "\n💀 PID del proceso a terminar: "
                read pid
                if [[ $pid =~ ^[0-9]+$ ]]; then
                    echo "¿Confirmas terminar proceso $pid? (s/n)"
                    read confirmar
                    case $confirmar in
                        s|S|y|Y|yes|YES)
                            kill "$pid" 2>/dev/null && echo -e "${GREEN}✅ Proceso terminado${NC}" || echo -e "${RED}❌ Error${NC}"
                            ;;
                        *)
                            echo "Cancelado"
                            ;;
                    esac
                else
                    echo -e "${RED}❌ PID inválido${NC}"
                fi
                read -p "Presiona Enter para continuar..."
                ;;
            5)
                echo -e "\n${BLUE}Monitoreo (presiona 'q' para salir):${NC}"
                top
                ;;
            0)
                break
                ;;
            *)
                echo -e "${RED}❌ Opción inválida${NC}"
                sleep 1
                ;;
        esac
    done
}

# Función principal
main() {
    while true; do
        mostrar_menu_principal
        read opcion
        
        case $opcion in
            1)
                menu_archivos
                ;;
            2)
                menu_procesos
                ;;
            3)
                echo -e "\n${YELLOW}🌐 Módulo de red en desarrollo...${NC}"
                sleep 2
                ;;
            4)
                echo -e "\n${YELLOW}👥 Módulo de usuarios en desarrollo...${NC}"
                sleep 2
                ;;
            5)
                clear
                echo -e "${BLUE}📊 INFORMACIÓN DEL SISTEMA${NC}"
                echo "=========================="
                echo -e "${CYAN}Sistema:${NC} $(uname -s)"
                echo -e "${CYAN}Hostname:${NC} $(hostname)"
                echo -e "${CYAN}Uptime:${NC} $(uptime -p 2>/dev/null || uptime)"
                echo -e "${CYAN}Memoria:${NC}"
                free -h
                echo -e "${CYAN}Disco:${NC}"
                df -h | grep -v tmpfs
                read -p "Presiona Enter para continuar..."
                ;;
            6)
                echo -e "\n${YELLOW}🛠️ Herramientas de mantenimiento en desarrollo...${NC}"
                sleep 2
                ;;
            0)
                echo -e "\n${GREEN}👋 ¡Hasta luego!${NC}"
                exit 0
                ;;
            *)
                echo -e "\n${RED}❌ Opción inválida. Usa 0-6.${NC}"
                sleep 2
                ;;
        esac
    done
}

# Ejecutar programa
main

Casos Prácticos con Case

Procesador de archivos por extensión Copiar
#!/bin/bash
# Procesador automático de archivos según su extensión

procesar_archivo() {
    local archivo="$1"
    local extension="${archivo##*.}"
    
    echo "Procesando: $archivo"
    echo "Extensión detectada: $extension"
    
    case "$extension" in
        # Archivos de texto
        txt|log|conf|config)
            echo "📄 Archivo de texto detectado"
            echo "Líneas: $(wc -l < "$archivo")"
            echo "Palabras: $(wc -w < "$archivo")"
            echo "Primeras 5 líneas:"
            head -5 "$archivo"
            ;;
        
        # Archivos de imagen
        jpg|jpeg|png|gif|bmp|svg)
            echo "🖼️  Archivo de imagen detectado"
            if command -v identify >/dev/null; then
                identify "$archivo"
            else
                echo "Instala ImageMagick para más información"
            fi
            ls -lh "$archivo"
            ;;
        
        # Archivos de video
        mp4|avi|mkv|mov|webm)
            echo "🎥 Archivo de video detectado"
            if command -v ffprobe >/dev/null; then
                ffprobe -v quiet -show_format -show_streams "$archivo" | grep -E "duration|width|height|codec_name"
            else
                echo "Instala FFmpeg para análisis detallado"
            fi
            ls -lh "$archivo"
            ;;
        
        # Archivos comprimidos
        zip|rar|7z|tar|gz|tar.gz|tgz)
            echo "📦 Archivo comprimido detectado"
            case "$extension" in
                zip)
                    unzip -l "$archivo" | head -20
                    ;;
                tar|tar.gz|tgz)
                    tar -tzf "$archivo" 2>/dev/null | head -20 || tar -tf "$archivo" | head -20
                    ;;
                *)
                    echo "Tipo de archivo comprimido: $extension"
                    ls -lh "$archivo"
                    ;;
            esac
            ;;
        
        # Scripts ejecutables
        sh|bash|py|pl|rb)
            echo "🔧 Script ejecutable detectado"
            echo "Tipo: $extension"
            echo "¿Es ejecutable? $([[ -x "$archivo" ]] && echo "Sí" || echo "No")"
            echo "Primeras líneas del script:"
            head -10 "$archivo"
            ;;
        
        # Documentos
        pdf|doc|docx|odt)
            echo "📚 Documento detectado"
            echo "Tipo: $extension"
            if command -v pdfinfo >/dev/null && [[ "$extension" == "pdf" ]]; then
                pdfinfo "$archivo"
            fi
            ls -lh "$archivo"
            ;;
        
        # Archivos sin extensión o desconocidos
        "$archivo")
            echo "❓ Archivo sin extensión"
            echo "Intentando detectar tipo:"
            file "$archivo"
            ;;
        
        *)
            echo "❓ Extensión desconocida: $extension"
            echo "Información del archivo:"
            file "$archivo"
            ls -lh "$archivo"
            ;;
    esac
    
    echo "───────────────────────────────────"
}

# Función principal
main() {
    if [[ $# -eq 0 ]]; then
        echo "Uso: $0 archivo1 [archivo2 ...]"
        echo "O arrastra archivos aquí:"
        read -p "Archivo: " archivo
        [[ -n "$archivo" ]] && procesar_archivo "$archivo"
    else
        for archivo in "$@"; do
            if [[ -f "$archivo" ]]; then
                procesar_archivo "$archivo"
            else
                echo "❌ No encontrado: $archivo"
                echo "───────────────────────────────────"
            fi
        done
    fi
}

main "$@"

Ejercicios Prácticos

Ejercicio 1: Calculadora con Menú

Crea una calculadora interactiva usando case:

calculadora.sh Copiar
#!/bin/bash
# Plantilla para calculadora

while true; do
    clear
    echo "╔════════════════════╗"
    echo "║    🧮 CALCULADORA   ║"
    echo "╚════════════════════╝"
    echo
    echo "1) Sumar"
    echo "2) Restar"
    echo "3) Multiplicar"
    echo "4) Dividir"
    echo "5) Potencia"
    echo "6) Raíz cuadrada"
    echo "0) Salir"
    echo
    echo -n "Opción: "
    read opcion
    
    case $opcion in
        1|suma|+)
            # TODO: Implementar suma
            echo "Ingresa dos números:"
            read -p "Número 1: " num1
            read -p "Número 2: " num2
            # resultado = ?
            ;;
        2|resta|-)
            # TODO: Implementar resta
            ;;
        3|multiplicacion|*)
            # TODO: Implementar multiplicación
            ;;
        4|division|/)
            # TODO: Implementar división con validación
            ;;
        5|potencia|^|**)
            # TODO: Implementar potencia
            ;;
        6|raiz|sqrt)
            # TODO: Implementar raíz cuadrada
            ;;
        0|salir|exit|quit)
            echo "¡Hasta luego!"
            exit 0
            ;;
        *)
            echo "❌ Opción no válida"
            sleep 1
            ;;
    esac
    
    read -p "Presiona Enter para continuar..."
done
Ejercicio 2: Gestor de Servicios

Desarrolla un gestor de servicios del sistema:

gestor_servicios.sh Copiar
#!/bin/bash
# Plantilla para gestor de servicios

echo "🔧 GESTOR DE SERVICIOS"
echo "====================="
echo
echo "Servicio a gestionar:"
read servicio

echo "¿Qué acción realizar?"
echo "1) start - Iniciar"
echo "2) stop - Detener"
echo "3) restart - Reiniciar"
echo "4) status - Ver estado"
echo "5) enable - Habilitar al inicio"
echo "6) disable - Deshabilitar al inicio"
echo
read accion

# TODO: Implementar case para las acciones
case $accion in
    1|start|iniciar)
        # systemctl start $servicio
        ;;
    2|stop|detener)
        # systemctl stop $servicio
        ;;
    3|restart|reiniciar)
        # systemctl restart $servicio
        ;;
    # TODO: Completar casos restantes
    *)
        echo "Acción no reconocida"
        ;;
esac
Ejercicio Avanzado: Instalador Interactivo

Crea un instalador que detecte el sistema operativo y use case para diferentes flujos: