Variables y Expansión

Domina el sistema de variables de Bash y las técnicas de expansión para crear scripts dinámicos y poderosos

Módulo 2 ⏱️ 40-45 min 📊 Variables 🔄 Expansión 📚 Principiante

Variables en Bash

Las variables son contenedores que almacenan datos (texto, números, rutas de archivos, etc.) y permiten que tus scripts sean dinámicos y reutilizables. En Bash, las variables son fundamentalmente cadenas de texto, pero pueden interpretarse como números según el contexto.

Declaración y Asignación

Sintaxis básica de variables Copiar
#!/bin/bash

# Asignación básica (sin espacios alrededor del =)
nombre="Juan"
edad=25
directorio="/home/usuario"

# Usando las variables
echo "Nombre: $nombre"
echo "Edad: $edad años"
echo "Directorio: $directorio"

# Reasignación
nombre="María"
echo "Nuevo nombre: $nombre"
Reglas importantes
  • No debe haber espacios alrededor del signo =
  • Los nombres de variables son case-sensitive (nombreNOMBRE)
  • Deben empezar con letra o guión bajo, no con número
  • Pueden contener letras, números y guiones bajos
$ ./variables_basicas.sh
Nombre: Juan
Edad: 25 años
Directorio: /home/usuario
Nuevo nombre: María

Expansión de Variables

Bash ofrece varias formas de expandir (acceder al valor de) las variables:

$variable

Forma simple, la más común.

echo $nombre → Juan

${variable}

Forma segura, delimita claramente el nombre.

echo ${nombre}_apellido
Ejemplos prácticos de expansión Copiar
#!/bin/bash

archivo="documento"
extension="txt"

# Problema: expansión ambigua
echo "Archivo: $archivo.pdf"     # ✅ Funciona
echo "Archivo: $archivo_backup"  # ❌ Busca variable 'archivo_backup'

# Solución: usar llaves
echo "Archivo: ${archivo}.pdf"   # ✅ Funciona
echo "Archivo: ${archivo}_backup" # ✅ Funciona

# Concatenación de variables
ruta_completa="${HOME}/${archivo}.${extension}"
echo "Ruta completa: $ruta_completa"

# Variables en strings
mensaje="El usuario $USER tiene $((RANDOM % 100)) puntos"
echo "$mensaje"

Comillas: Simples vs Dobles

El tipo de comillas afecta cómo Bash interpreta las variables:

Diferencias entre comillas Copiar
#!/bin/bash

nombre="Juan"
fecha=$(date)

# Comillas dobles: permite expansión
echo "Hola $nombre, hoy es $fecha"
# Salida: Hola Juan, hoy es Tue Oct 15 14:30:25 UTC 2024

# Comillas simples: literal (sin expansión)
echo 'Hola $nombre, hoy es $fecha'
# Salida: Hola $nombre, hoy es $fecha

# Sin comillas: expansión + división de palabras
archivo="mi archivo.txt"
ls $archivo    # ❌ Bash ve "mi" y "archivo.txt" como argumentos separados
ls "$archivo"  # ✅ Correcto

# Casos especiales
echo "El precio es \$25"        # Escapar el $
echo "Ruta: \"$HOME/docs\""     # Escapar comillas dentro de comillas
Regla de oro

Siempre usa comillas dobles alrededor de variables, especialmente si pueden contener espacios: "$variable"

Sustitución de Comandos

Puedes capturar la salida de un comando y usarla como valor de una variable:

Dos sintaxis para sustitución Copiar
#!/bin/bash

# Sintaxis moderna (recomendada)
fecha_actual=$(date)
usuarios_conectados=$(who | wc -l)
directorio_actual=$(pwd)

echo "Fecha: $fecha_actual"
echo "Usuarios conectados: $usuarios_conectados"
echo "Directorio: $directorio_actual"

# Sintaxis antigua (funciona pero no se recomienda)
fecha_antigua=`date`

# Comandos anidados
año_actual=$(date +%Y)
respaldo_nombre="backup_${año_actual}_$(date +%m%d_%H%M).tar.gz"
echo "Nombre del respaldo: $respaldo_nombre"

# Asignar a variables para reutilizar
timestamp=$(date +%Y%m%d_%H%M%S)
log_file="/var/log/mi_script_${timestamp}.log"
echo "Archivo de log: $log_file"
$ ./sustitucion_comandos.sh
Fecha: Tue Oct 15 14:30:25 UTC 2024
Usuarios conectados: 2
Directorio: /home/usuario/scripts
Nombre del respaldo: backup_2024_1015_1430.tar.gz
Archivo de log: /var/log/mi_script_20241015_143025.log

Variables de Entorno

Las variables de entorno son variables especiales que el sistema mantiene y que están disponibles para todos los procesos:

Variables de entorno comunes Copiar
#!/bin/bash

echo "=== INFORMACIÓN DEL USUARIO ==="
echo "Usuario actual: $USER"
echo "UID del usuario: $UID"
echo "Directorio home: $HOME"
echo "Shell actual: $SHELL"

echo -e "\n=== INFORMACIÓN DEL SISTEMA ==="
echo "Hostname: $HOSTNAME"
echo "Sistema operativo: $OSTYPE"
echo "Directorio actual: $PWD"
echo "Directorio anterior: $OLDPWD"

echo -e "\n=== CONFIGURACIÓN ==="
echo "PATH: $PATH"
echo "Idioma: $LANG"
echo "Editor por defecto: $EDITOR"

echo -e "\n=== PROCESO ACTUAL ==="
echo "PID del script: $$"
echo "PID del proceso padre: $PPID"

Creando y exportando variables

Variables locales vs variables de entorno Copiar
#!/bin/bash

# Variable local (solo existe en este script)
mi_variable="valor local"

# Convertir en variable de entorno (disponible para subprocesos)
export mi_variable
# o directamente:
export mi_variable_global="valor global"

# Verificar si una variable está exportada
if [[ -v HOME ]]; then
    echo "HOME está definida: $HOME"
fi

# Ver todas las variables de entorno
echo "Variables de entorno:"
env | grep "mi_variable"

# Eliminar variable de entorno
unset mi_variable_global

Expansión Avanzada de Parámetros

Bash ofrece técnicas avanzadas para manipular variables:

Valores por defecto y validación Copiar
#!/bin/bash

# Valores por defecto
nombre=${1:-"Usuario Anónimo"}    # Si $1 está vacío, usar "Usuario Anónimo"
puerto=${PORT:-8080}              # Si PORT no existe, usar 8080
archivo=${CONFIG_FILE:-"/etc/default.conf"}

echo "Nombre: $nombre"
echo "Puerto: $puerto"
echo "Archivo config: $archivo"

# Validar que variables obligatorias existen
base_datos=${DATABASE_URL:?"ERROR: DATABASE_URL es obligatoria"}

# Asignar valor por defecto solo si la variable está vacía
directorio=${WORK_DIR:="/tmp/trabajo"}

# Usar valor alternativo si variable existe y no está vacía
modo=${DEBUG_MODE:+"modo debug activo"}
echo "Modo: ${modo:-"modo normal"}"

Manipulación de strings

Extracción y reemplazo Copiar
#!/bin/bash

ruta="/home/usuario/documentos/archivo.txt"

# Longitud de string
echo "Longitud: ${#ruta} caracteres"

# Extraer substring (posición:longitud)
echo "Substring: ${ruta:6:7}"     # "usuario"

# Eliminar desde el final (más corto)
echo "Sin extensión: ${ruta%.*}"  # /home/usuario/documentos/archivo

# Eliminar desde el final (más largo)
echo "Solo directorio: ${ruta%/*}" # /home/usuario/documentos

# Eliminar desde el principio (más corto)
echo "Solo nombre: ${ruta##*/}"   # archivo.txt

# Eliminar desde el principio (más largo)  
echo "Sin /home: ${ruta#/*/}"     # usuario/documentos/archivo.txt

# Reemplazar primera ocurrencia
echo "Cambiar usuario: ${ruta/usuario/admin}"

# Reemplazar todas las ocurrencias
texto="one two one three one"
echo "Cambiar 'one' por '1': ${texto//one/1}"

# Reemplazar al inicio
echo "Cambiar ruta base: ${ruta/#\/home/\/opt}"
$ ./manipulacion_strings.sh
Longitud: 34 caracteres
Substring: usuario
Sin extensión: /home/usuario/documentos/archivo
Solo directorio: /home/usuario/documentos
Solo nombre: archivo.txt
Sin /home: usuario/documentos/archivo.txt
Cambiar usuario: /home/admin/documentos/archivo.txt
Cambiar 'one' por '1': 1 two 1 three 1
Cambiar ruta base: /opt/usuario/documentos/archivo.txt

Variables Especiales

Bash proporciona variables especiales automáticas muy útiles:

Variables automáticas del sistema Copiar
#!/bin/bash

echo "=== INFORMACIÓN DEL SCRIPT ==="
echo "Nombre del script: $0"
echo "Número de parámetros: $#"
echo "Todos los parámetros: $*"
echo "Todos los parámetros (array): $@"
echo "PID del script: $$"
echo "Código de salida del último comando: $?"

echo -e "\n=== PARÁMETROS INDIVIDUALES ==="
echo "Primer parámetro: $1"
echo "Segundo parámetro: $2"
echo "Tercer parámetro: $3"

echo -e "\n=== INFORMACIÓN ADICIONAL ==="
echo "Opciones de Bash actuales: $-"
echo "PID del último proceso en background: $!"

# Ejemplo práctico
if [ $# -eq 0 ]; then
    echo "Uso: $0  [archivo2] [archivo3]"
    exit 1
fi

echo "Procesando $# archivos..."
for archivo in "$@"; do
    echo "- Procesando: $archivo"
done
Diferencia entre $* y $@
  • $*: Une todos los parámetros en una sola cadena
  • $@: Mantiene los parámetros como elementos separados
  • Con comillas: "$*" vs "$@" - la diferencia es crucial en bucles

Aritmética con Variables

Aunque Bash trata las variables como strings, puede realizar operaciones aritméticas:

Operaciones aritméticas Copiar
#!/bin/bash

# Declarar variables enteras
declare -i numero1=10
declare -i numero2=5

# Aritmética básica
suma=$((numero1 + numero2))
resta=$((numero1 - numero2))  
multiplicacion=$((numero1 * numero2))
division=$((numero1 / numero2))
modulo=$((numero1 % numero2))

echo "Número 1: $numero1"
echo "Número 2: $numero2"
echo "Suma: $suma"
echo "Resta: $resta"
echo "Multiplicación: $multiplicacion"
echo "División: $division"
echo "Módulo: $modulo"

# Operaciones más complejas
potencia=$((numero1 ** 2))
echo "10 al cuadrado: $potencia"

# Incremento y decremento
contador=0
echo "Contador inicial: $contador"
((contador++))
echo "Después de ++: $contador"
((contador += 5))
echo "Después de += 5: $contador"

# Números aleatorios
aleatorio=$((RANDOM % 100 + 1))  # Entre 1 y 100
echo "Número aleatorio: $aleatorio"

# Comparaciones aritméticas (retornan 0 o 1)
resultado=$((numero1 > numero2))
echo "¿$numero1 > $numero2?: $resultado"
$ ./aritmetica.sh
Número 1: 10
Número 2: 5
Suma: 15
Resta: 5
Multiplicación: 50
División: 2
Módulo: 0
10 al cuadrado: 100
Contador inicial: 0
Después de ++: 1
Después de += 5: 6
Número aleatorio: 42
¿10 > 5?: 1

Ejercicios Prácticos

Ejercicio 1: Información del usuario

Crea un script que muestre información personalizada usando variables:

info_usuario.sh Copiar
#!/bin/bash

# Obtener información del usuario
usuario_actual="$USER"
directorio_home="$HOME"
shell_actual="$SHELL"
fecha_actual=$(date "+%A, %d de %B de %Y")
hora_actual=$(date "+%H:%M:%S")
tiempo_activo=$(uptime -p 2>/dev/null || uptime | cut -d',' -f1)

# Información del directorio
directorio_actual=$(pwd)
archivos_directorio=$(ls -1 | wc -l)
espacio_usado=$(du -sh . | cut -f1)

# Mostrar información
echo "======================================"
echo "    INFORMACIÓN DEL USUARIO"
echo "======================================"
echo "Usuario: $usuario_actual"
echo "Directorio home: $directorio_home"
echo "Shell: ${shell_actual##*/}"
echo "Fecha: $fecha_actual"
echo "Hora: $hora_actual"
echo "Sistema activo: $tiempo_activo"
echo
echo "DIRECTORIO ACTUAL:"
echo "Ubicación: $directorio_actual"
echo "Archivos/carpetas: $archivos_directorio"
echo "Espacio usado: $espacio_usado"
echo "======================================"
Ejercicio 2: Calculadora simple

Script que acepta dos números como parámetros y realiza operaciones:

calculadora.sh Copiar
#!/bin/bash

# Validar parámetros
if [ $# -ne 2 ]; then
    echo "Uso: $0  "
    echo "Ejemplo: $0 10 5"
    exit 1
fi

# Obtener parámetros
num1="$1"
num2="$2"

# Validar que son números
if ! [[ "$num1" =~ ^-?[0-9]+$ ]] || ! [[ "$num2" =~ ^-?[0-9]+$ ]]; then
    echo "Error: Ambos parámetros deben ser números enteros"
    exit 1
fi

# Realizar operaciones
suma=$((num1 + num2))
resta=$((num1 - num2))
multiplicacion=$((num1 * num2))

# División con validación
if [ $num2 -eq 0 ]; then
    division="No definida (división por cero)"
    modulo="No definido (división por cero)"
else
    division=$((num1 / num2))
    modulo=$((num1 % num2))
fi

# Mostrar resultados
echo "========================================="
echo "    CALCULADORA BASH"
echo "========================================="
echo "Número 1: $num1"
echo "Número 2: $num2"
echo "---------"
echo "Suma:           $num1 + $num2 = $suma"
echo "Resta:          $num1 - $num2 = $resta"
echo "Multiplicación: $num1 × $num2 = $multiplicacion"
echo "División:       $num1 ÷ $num2 = $division"
echo "Módulo:         $num1 % $num2 = $modulo"
echo "========================================="
Ejercicio de práctica

Crea un script que:

  1. Acepte un nombre de archivo como parámetro
  2. Extraiga el nombre sin extensión
  3. Cree un archivo de respaldo con timestamp
  4. Muestre información sobre el archivo original

¡Intenta combinarlo con todo lo que has aprendido sobre variables!