¿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
patrón1)
;;
;;
;;
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
#!/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
#!/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:
#!/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:
#!/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:
- Detectar OS (Linux, macOS, Windows/WSL)
- Detectar distribución de Linux
- Instalar dependencias según el sistema
- Configurar servicios específicos por plataforma