variables-y-datos
Variables y datos
Section titled “Variables y datos”Cómo almacenar y manipular información en Bash: variables, comillas, argumentos, entrada del usuario, aritmética, cadenas, arrays y expansiones.
Variables
Section titled “Variables”Bash no tiene tipos estrictos: todo es texto salvo que se indique lo contrario.
nombre="mundo" # asignación: SIN espacios alrededor del =echo "Hola, $nombre" # uso con $echo "${nombre}s" # llaves para delimitar el nombreunset nombre # eliminarReglas de nombres: letras, números y _; no pueden empezar por número; distingue mayúsculas de minúsculas.
Atributos con declare
Section titled “Atributos con declare”declare -i numero=5 # enterodeclare -r CONSTANTE=10 # solo lectura (equivale a readonly)declare -x VAR=valor # exportada (equivale a export)declare -a lista # array indexadodeclare -A mapa # array asociativoreadonly MAX=3MAX=4 # error: variable de solo lecturaResultado de un comando en una variable
Section titled “Resultado de un comando en una variable”fecha=$(date +%F)usuarios=$(wc -l < /etc/passwd)Errores típicos
Section titled “Errores típicos”nombre = "x" # incorrecto: Bash lo interpreta como un comando "nombre"nombre="x" # correctoComillas y escapes
Section titled “Comillas y escapes”| Tipo | Efecto |
|---|---|
'texto' |
Literal. No expande nada. |
"texto" |
Expande variables ($var), comandos ($(...)) y aritmética; evita separar por espacios. |
\c |
Escapa el carácter siguiente. |
$'texto' |
Interpreta secuencias como \n, \t. |
var="mundo"echo 'Hola $var' # Hola $varecho "Hola $var" # Hola mundoecho "Precio: \$5" # Precio: $5echo $'Linea1\nLinea2'Por qué entrecomillar variables
Section titled “Por qué entrecomillar variables”fichero="mi documento.txt"rm $fichero # intenta borrar "mi" y "documento.txt"rm "$fichero" # correctoRegla práctica: entrecomillar siempre "$variable" salvo que se quiera explícitamente la separación por palabras o el globbing.
echo y printf
Section titled “echo y printf”echo -e "a\tb\nc" # -e interpreta escapesecho -n "sin salto" # -n evita el salto de líneaprintf '%s tiene %d años\n' "Ana" 30 # más predecible y portableArgumentos y variables especiales
Section titled “Argumentos y variables especiales”Argumentos posicionales
Section titled “Argumentos posicionales”#!/bin/bashecho "Script: $0"echo "Primero: $1"echo "Segundo: $2"echo "Total: $#"echo "Todos: $@"./script.sh uno dos# Primero: uno# Segundo: dos# Total: 2A partir del décimo argumento hacen falta llaves: ${10}.
Tabla de variables especiales
Section titled “Tabla de variables especiales”| Variable | Contenido |
|---|---|
$0 |
Nombre del script |
$1 … $9, ${10} |
Argumentos posicionales |
$# |
Número de argumentos |
$@ |
Todos los argumentos (cada uno por separado si va entre comillas) |
$* |
Todos los argumentos (como una sola cadena si va entre comillas) |
$? |
Código de salida del último comando |
$$ |
PID del proceso actual |
$! |
PID del último proceso lanzado en segundo plano |
“$@” frente a “$*”
Section titled ““$@” frente a “$*””for arg in "$@"; do echo "[$arg]"; done # respeta cada argumento, incluso con espaciosCasi siempre se usa "$@".
Descarta el primer argumento y desplaza los demás.
while [[ $# -gt 0 ]]; do echo "Procesando $1" shiftdoneValidar argumentos
Section titled “Validar argumentos”if [[ $# -lt 1 ]]; then echo "Uso: $0 <fichero>" >&2 exit 1fiLectura de datos con read
Section titled “Lectura de datos con read”read -r nombre # lee una línearead -rp "Nombre: " nombre # con mensajeread -rsp "Clave: " clave; echo # sin eco (el echo final da el salto de línea)read -t 5 -rp "Responde: " resp # tiempo límite de 5 sread -n 1 -rp "¿Seguir? (s/n) " r # un solo carácter| Opción | Efecto |
|---|---|
-r |
No interpreta \ (recomendado siempre) |
-p |
Muestra un mensaje |
-s |
Silencioso (no muestra lo escrito) |
-t n |
Tiempo máximo de espera |
-n n |
Lee solo n caracteres |
-a arr |
Guarda las palabras en un array |
Sin nombre de variable, el valor queda en $REPLY.
Separar campos con IFS
Section titled “Separar campos con IFS”linea="root:x:0:0"IFS=: read -r usuario _ uid gid <<< "$linea"echo "$usuario $uid" # root 0Confirmación
Section titled “Confirmación”read -rp "¿Continuar? (s/n) " r[[ $r == [sS] ]] || exit 0Aritmética
Section titled “Aritmética”Bash opera solo con enteros.
a=7; b=2echo $((a + b)) # 9echo $((a / b)) # 3 (división entera)echo $((a % b)) # 1 (resto)echo $((a ** b)) # 49 (potencia)Formas de calcular
Section titled “Formas de calcular”resultado=$((a * b)) # expansión aritmética (la más usada)(( a++ )) # evaluación sin devolver valor(( a > b )) && echo "a es mayor"let c=a+b # forma antiguadeclare -i d=a+b # variable enteraIncremento: ((contador++)) o contador=$((contador+1)).
Con set -e, ((x++)) cuando x vale 0 devuelve código 1 y puede abortar el script. Es preferible x=$((x+1)).
Decimales
Section titled “Decimales”Bash no los admite; se delega en otras herramientas:
echo "scale=2; 7/2" | bc # 3.50awk 'BEGIN { printf "%.2f\n", 7/2 }' # 3.50Números aleatorios y secuencias
Section titled “Números aleatorios y secuencias”echo $RANDOM # 0 a 32767echo $((RANDOM % 100)) # 0 a 99seq 1 5 # 1 2 3 4 5Cadenas y parameter expansion
Section titled “Cadenas y parameter expansion”Permite manipular el valor de una variable sin comandos externos.
f="informe.final.txt"Longitud y subcadenas
Section titled “Longitud y subcadenas”| Expresión | Resultado | Significado |
|---|---|---|
${#f} |
17 |
Longitud |
${f:0:7} |
informe |
Desde posición 0, 7 caracteres |
${f:8} |
final.txt |
Desde la posición 8 hasta el final |
${f: -3} |
txt |
Últimos 3 caracteres (espacio antes del -) |
Eliminar patrones
Section titled “Eliminar patrones”| Expresión | Resultado | Significado |
|---|---|---|
${f#*.} |
final.txt |
Quita el prefijo más corto que coincida |
${f##*.} |
txt |
Quita el prefijo más largo (extensión) |
${f%.*} |
informe.final |
Quita el sufijo más corto |
${f%%.*} |
informe |
Quita el sufijo más largo |
Regla mnemotécnica: # actúa por la izquierda, % por la derecha; doble símbolo = coincidencia más larga.
Sustituir
Section titled “Sustituir”echo "${f/final/inicial}" # informe.inicial.txt (primera coincidencia)echo "${f//./_}" # informe_final_txt (todas)Mayúsculas y minúsculas (Bash 4+)
Section titled “Mayúsculas y minúsculas (Bash 4+)”n="Mundo"echo "${n^^}" # MUNDOecho "${n,,}" # mundoecho "${n^}" # primera en mayúsculaValores por defecto
Section titled “Valores por defecto”| Expresión | Efecto |
|---|---|
${v:-defecto} |
Usa defecto si v está vacía o sin definir (no la modifica) |
${v:=defecto} |
Igual, pero además asigna el valor a v |
${v:?mensaje} |
Si v está vacía, muestra el mensaje y aborta |
${v:+alternativa} |
Usa alternativa solo si v tiene valor |
destino="${1:-/tmp}" # primer argumento o /tmp por defectoComparar cadenas
Section titled “Comparar cadenas”[[ $a == $b ]] # igualdad[[ $a == pre* ]] # patrón[[ $a =~ ^[0-9]+$ ]] # expresión regularArrays
Section titled “Arrays”Colección indexada desde 0.
frutas=("manzana" "pera" "uva")frutas[3]="kiwi"frutas+=("melón") # añadir al finalAcceso
Section titled “Acceso”| Expresión | Resultado |
|---|---|
${frutas[0]} |
Primer elemento |
${frutas[-1]} |
Último elemento (Bash 4.3+) |
${frutas[@]} |
Todos los elementos |
${#frutas[@]} |
Número de elementos |
${!frutas[@]} |
Índices |
${frutas[@]:1:2} |
Subconjunto (desde 1, 2 elementos) |
Recorrer
Section titled “Recorrer”for f in "${frutas[@]}"; do echo "$f"done
for i in "${!frutas[@]}"; do echo "$i: ${frutas[$i]}"doneOperaciones
Section titled “Operaciones”unset 'frutas[1]' # eliminar un elemento (deja hueco en los índices)copia=("${frutas[@]}") # copiarmapfile -t lineas < fichero.txt # cada línea del fichero, un elementolineas=($(cat fichero.txt)) # evitar: separa por espacios y aplica globbingEntrecomillar siempre "${array[@]}" para conservar elementos con espacios.
Arrays asociativos
Section titled “Arrays asociativos”Pares clave-valor. Requieren declare -A (Bash 4+).
declare -A puertospuertos[ssh]=22puertos[http]=80puertos[https]=443
echo "${puertos[ssh]}" # 22Declaración en una línea:
bash
declare -A puertos=([ssh]=22 [http]=80 [https]=443)Recorrer
Section titled “Recorrer”bash
for servicio in "${!puertos[@]}"; do echo "$servicio -> ${puertos[$servicio]}"doneOperaciones
Section titled “Operaciones”bash
echo "${#puertos[@]}" # número de pares[[ -v puertos[ftp] ]] || echo "ftp no definido" # comprobar si existe la claveunset 'puertos[http]' # eliminarEl orden de recorrido de un array asociativo no está garantizado.
Expansiones
Section titled “Expansiones”La shell procesa cada línea aplicando expansiones en este orden aproximado:
- Llaves
{a,b} - Tilde
~ - Parámetros y variables
$var, aritmética$(( )), sustitución de comandos$( ) - Separación de palabras
- Globbing
*,?,[...]
Expansión de llaves
Section titled “Expansión de llaves”bash
echo {1..5} # 1 2 3 4 5echo {a..e} # a b c d eecho {01..10} # 01 02 ... 10echo {0..20..5} # 0 5 10 15 20echo archivo_{a,b,c}.txt # archivo_a.txt archivo_b.txt archivo_c.txtmkdir -p proyecto/{src,docs,tests}Sustitución de comandos
Section titled “Sustitución de comandos”echo "Hoy es $(date +%A)"total=$(ls | wc -l)Se prefiere $(...) frente a las comillas invertidas `...`, porque se puede anidar y es más legible.
cd ~ # directorio personalls ~/binExpansión aritmética
Section titled “Expansión aritmética”echo "Resultado: $((5 * 4))"Separación de palabras
Section titled “Separación de palabras”El resultado de una expansión sin comillas se separa según IFS (espacio, tabulador, salto de línea) y se le aplica globbing. Por eso se entrecomillan las variables.