Variables en Bash: $VAR vs ${VAR} y por qué siempre debes usar comillas dobles
Variables en Bash: $VAR vs ${VAR} y por qué siempre debes usar comillas dobles
Introducción
Si alguna vez escribiste un script en Bash, seguramente te encontraste con la necesidad de almacenar datos en variables y luego reutilizarlos en diferentes partes del script. El concepto en sí es simple: asignás un valor a una variable y después podés referenciarlo usando un signo de dólar ($). Sin embargo, hay un detalle sutil que muchos principiantes pasan por alto y que puede causar errores difíciles de depurar: la diferencia entre $VAR y ${VAR} y, más importante aún, la necesidad de siempre citar las variables con comillas dobles ("").
Este artículo explica en profundidad cómo funcionan las variables en Bash, por qué la sintaxis expandida ${VAR} existe, y, lo que es más crucial, por qué siempre debes envolver las referencias a variables con comillas dobles. También verás ejemplos prácticos y ejecutables con su salida esperada, para que puedas ver el impacto de cada opción de quoting directamente en tu terminal.
Al final de esta lectura, tendrás una comprensión sólida de:
- Cómo declarar y expandir variables en Bash.
- La diferencia entre
$VARy${VAR}y cuándo usar cada una. - El papel de las comillas dobles en la expansión de variables y por qué son tu mejor defensa contra errores de “splitting de palabras” y “globbing de caracteres comodín”.
- Ejemplos claros y listos para copiar que demuestran el impacto del quoting (o la falta de él) en casos reales.
- Patrones de mejores prácticas que puedes aplicar de inmediato en cualquier script.
Así que, prepárate para dominar un aspecto fundamental del scripting en Bash que marcará la diferencia entre scripts que funcionan y scripts que se rompen.
¿Qué es una variable en Bash?
Una variable en Bash es esencialmente un contenedor que almacena un valor que podés reutilizar. La syntax para asignar un valor es simple:
VAR="ejemplo"o sin comillas (si sabés que el valor no contiene espacios o caracteres especiales):
VAR=ejemploEn ambos casos, VAR se convierte en un nombre de variable, y "ejemplo" (o ejemplo) es el valor asociado. El signo de dolar ($) es el operador que le indica a Bash que debe expandir (es decir, reemplazar) el nombre de la variable con su valor contenido.
Variable simple: $VAR
Expandión con llaves: ${VAR}
Ambas formas hacen lo mismo, pero existen por razones históricas y de legibilidad. La versión con llaves se vuelve especialmente útil en tres situaciones comunes:
- Variables que comienzan con un número (aunque Bash permite nombres así, la forma con llaves hace la expansión más clara).
- Variables que contienen muchos caracteres (por ejemplo,
MY_LONG_VARIABLE_NAME) – las llaves evitan ambigüedades para Bash. - Extracción de subcadena, sustitución o desbordamiento (por ejemplo,
${VAR%%.*}) – el quoting con llaves es necesario para esas operaciones avanzadas.
Aún así, para una simple sustitución, $VAR y ${VAR} son intercambiables.
Ejemplo rápido: $VAR vs ${VAR}
# Ejemplo 1: Variable simple
NOMBRE="Juan"
echo "$NOMBRE"
echo "${NOMBRE}"Salida esperada:
Juan
JuanAmbas líneas imprimen exactamente lo mismo. El script demuestra que, para una simple variable, podés usar el estilo corto o el largo sin afectar el resultado.
El caso por el cual las llaves existen: Casos donde necesitas ${VAR}
Aunque $VAR funciona para la mayoría de los casos, las llaves permiten un conjunto más amplio de operaciones. Veamos algunas cosas en las que ${VAR} es indispensable.
1. Variables que comienzan con un número
# Esto da error con $2VAR
2VAR="primero"
# echo $2VAR produce: comando no encontrado "2"
# La forma correcta:
echo "${2VAR}"Salida:
primero2. Nombres de variables largos
MY_SUPER_LONG_VARIABLE_NAME="valor"
# Seguro, pero un poco ambiguo:
echo $MY_SUPER_LONG_VARIABLE_NAME
# Mejor con llaves:
echo "${MY_SUPER_LONG_VARIABLE_NAME}"Salida:
valor
valor3. Operaciones avanzadas: eliminación de prefijos/sufijos, longitud, sustitución
TEXTO="archivo.txt"
# Obtener la parte sin extensión
echo "${TEXTO%%.*}" # archivo
# Longitud de la variable
echo "${#TEXTO}" # 9Salida:
archivo
9En cada uno de estos casos, las llaves no son solo una cuestión de estilo; son necesarias para que Bash analice correctamente la expansión.
Por qué siempre debes citar las variables con comillas dobles
Ahora llegamos al tema más importante. Incluso si $VAR y ${VAR} funcionan, siempre debes citar una variable con comillas dobles cuando la expandas:
VAR="valor con espacios"
echo $VAR # peligro: sin comillasEl resultado puede ser inesperado porque Bash realiza dos operaciones automáticas en una palabra no citada:
- Splitting de palabras: espacios y tabulaciones dividen la palabra en múltiples palabras.
- Globbing: caracteres comodín como
*,?,[se expanden a nombres de archivos coincidientes.
Si citás con comillas dobles, desactivás ambos comportamientos para esa palabra, conservando el valor original del lado izquierdo.
Mostrar el problema: Splitting de palabras y Globbing
1. Splitting de palabras
NOMBRE="Juan Pérez"
echo "Nombre sin comillas: $NOMBRE"
echo "Nombre con comillas: \"$NOMBRE\""Salida esperada:
Nombre sin comillas: Juan
Pérez
Nombre con comillas: Juan PérezPuedes ver cómo la falta de comillas divide el valor en dos tokens separados, mientras que las comillas dobles preservan el nombre completo.
2. Globbing (expansión de comodín)
ARCHIVO="*.txt"
echo "Sin comillas: $ARCHIVO"
echo "Con comillas: \"$ARCHIVO\""Salida esperada:
Sin comillas: *.txt
Con comillas: *.txtSi tuvieran archivos que coinciden con *.txt en el directorio actual, la versión sin comillas imprimiría cada nombre de archivo por separado (ya que * se expande), mientras que la versión con comillas mostraría la cadena literal *.txt. Este ejemplo demuestra por qué es importante citar tus variables: evita una expansión accidental cuando el valor contiene caracteres comodín.
Por qué las comillas simples no son siempre suficientes
A veces puedes pensar: “¿por qué no usar comillas simples? echo '$VAR'”. Las comillas simples previenen el splitting de palabras y el globbing, pero también desactivan la expansión de variables – el $ se tratará como texto, no como un marcador de posición para el valor. Así que echo '$VAR' imprime literalmente $VAR, no el contenido almacenado.
Las comillas dobles permiten que las variables se expandan, manteniendo al mismo tiempo las salvaguardas contra el splitting y el globbing para la palabra resultante.
Ejemplo combinado con espacios y caracteres comodín
PATTERNS="*.sh"
DIRECTORIO="Documentos/personas"
# Sin comillas: el shell trata cada parte como una entrada separada, causando errores
echo "Listando: $PATTERNS en $DIRECTORIO"
# Con comillas: preserva cada parte como una sola palabra
echo "Listando: \"$PATTERNS\" en \"$DIRECTORIO\""Salida esperada:
Listando: *.sh en Documentos/personas
Listando: *.sh en Documentos/personasIncluso si el patrón contiene un comodín, las comillas evitan que Bash lo trate como un comodín de expansión de ruta.
El estilo recomendado: siempre citar con comillas dobles
Un enfoque típico en scripts bien escritos es:
# Asignar con o sin comillas (ambos son aceptables)
VAR="valor con espacios"
# o
VAR=valor_sin_espacios
# Siempre expandir con comillas dobles
echo "El valor es: \"$VAR\""El script anterior demuestra un pattern claro: citar al asignar cuando puedas (especialmente si el valor puede contener espacios) y siempre citar al expandir. Esta consistencia elimina muchos errores sutiles.
Cuándo podés omitir las comillas
Hay situaciones seguras donde puedes omitir las comillas dobles:
- Variables simples sin espacios ni caracteres especiales:
VAR=hola; echo $VAR - Cuando querrías intencionalmente el splitting de palabras (raro, pero a veces necesario).
- Cuando estás construyendo manualmente un comando con
eval(usa con extrema precaución).
Incluso en estos casos, citar no hace daño (es solo un extra de caracteres). El riesgo de un error de typing o un cambio posterior en el valor que posteriormente incluya espacios hace que citar sea la opción predeterminada más segura.
Ejemplo completo: un script realista
Ahora veamos un script realista que procesa un nombre de usuario y un patrón de archivo, ilustrando las mejores prácticas de variables y quoting.
Script: procesar_usuario.sh
#!/usr/bin/env bash
# ---- Entrada del usuario (simulada) ----
NOMBRE_USUARIO="María García"
PATRÓN_ARCHIVO="*.pdf"
# ---- Lógica ----
# Crear un directorio basado en el nombre de usuario (con espacios)
DIRECTORIO_USUARIO="Documentos/${NOMBRE_USUARIO}"
mkdir -p "$DIRECTORIO_USUARIO"
# Copiar todos los PDFs (el patrón podría expandirse si no se cita)
cp "$PATRÓN_ARCHIVO" "$DIRECTORIO_USUARIO"/
# Listar el contenido del directorio recién creado
echo "Contenido de $DIRECTORIO_USUARIO:"
ls -1 "$DIRECTORIO_USUARIO"Explicación:
DIRECTORIO_USUARIOse construye interpolando el valor deNOMBRE_USUARIOdentro de una cadena. El${NOMBRE_USUARIO}hace la extracción clara.mkdir -p "$DIRECTORIO_USUARIO"cita la variable para evitar splitting de palabras si el nombre contiene espacios (es decir, “María García”).cp "$PATRÓN_ARCHIVO" "$DIRECTORIO_USUARIO"/cita el patrón para evitar la expansión de comodines que copiaría archivos individuales en lugar del patrón literal.ls -1 "$DIRECTORIO_USUARIO"cita la variable nuevamente para una impresión segura.
Al ejecutar este script en un entorno donde tienes algunos PDFs (*.pdf) y la carpeta Documentos existe, obtendrás:
Contenido de Documentos/María García:
Contrato.pdf
Factura.pdfSi omites las comillas alrededor de $PATRÓN_ARCHIVO, cp intentará copiar cada archivo coincidente individualmente, lo que puede causar un comportamiento inesperado (por ejemplo, sobrescribir archivos, perder la ruta objetivo). Citar protege contra eso.
Errores comunes y cómo evitarlos
| Error | Lo que sucede | Cómo evitarlo |
|---|---|---|
Variables sin comillas en echo |
Splitting de palabras, globbing, inserción de variables inesperadas. | Siempre usa echo "$VAR". |
| Comenzar una variable con un número | Bash trata $2Var como un comando. |
Usa ${2Var} o renombra. |
Olvidar citar una variable construida (${VAR} dentro de una cadena más grande) |
Mismo problema que con la variable simple. | Cita la palabra completa: "texto ${VAR} más". |
| Combinar comillas simples y dobles incorrectamente | Ruedas un escape innecesario. | Decide un estilo (" para expansión, ' para literales) y aplica consistente. |
Usar eval con variables sin citar |
Inyección de código. | Evita eval a menos que estés 100 % seguro; cita las entradas. |
La regla más importante es: si alguna vez puedes imaginar que el valor podría contener un espacio, una tabulación, un asterisco, un signo de interrogación, un corchete o un signo dolar, cita la variable.
Conclusión: El script de referencia rápido
Aquí tienes un script de referencia rápido que resume todo lo que aprendiste:
#!/usr/bin/env bash
# Ejemplo de assignment de variables con espacios y comodines
NOMBRE="Ana López"
PATRÓN="*.txt"
# Expandir con comillas dobles para preservar espacios y evitar globbing
echo "Nombre original: \"$NOMBRE\""
echo "Patrón original: \"$PATRÓN\""
# Construir una ruta usando quoting con llaves para claridad
DIRECTORIO="Documentos/${NOMBRE}"
mkdir -p "$DIRECTORIO"
# Copiar archivos usando el patrón citado
cp "$PATRÓN" "$DIRECTORIO"/
# Listar el contenido de forma segura
echo "Archivos en $DIRECTORIO:"
ls -1 "$DIRECTORIO"Al ejecutar este script (suponiendo que tienes archivos .txt en el directorio actual), verás cada variable impresa tal como la definiste, los directorios creados correctamente y los archivos copiados sin errores de splitting o globbing.
Resumen
- Las variables en Bash se declaran usando
NOMBRE=valory se expanden usando$NOMBREo${NOMBRE}. ${NOMBRE}es necesario cuando el nombre de la variable comienza con un número, es largo o necesitas operaciones avanzadas (eliminación de subcadenas, longitud, sustitución).- Siempre cita las variables con comillas dobles (
\"$VAR\") al expandirlas. Esto previene el splitting de palabras y el globbing, dos mecanismos que pueden cambiar drásticamente el significado de una variable. - Las comillas simples desactivan la expansión de variables, por lo que no son adecuadas para la expansión regular.
- Las mejores prácticas incluyen citar al asignar (especialmente cuando los valores pueden contener espacios) y citar al expandir, independientemente de los patrones esperados.
- Los scripts de ejemplo demuestran cómo el quoting correcto mantiene los scripts robustos ante valores aparentemente simples que luego adquieren espacios, tabulaciones o caracteres comodín.
Dominar el quoting de variables es uno de los pasos más rápidos para pasar de scripts en Bash que funcionan “por casualidad” a scripts en Bash confiables y mantenibles. La inversión de tiempo en citar cada variable desde el principio reduce drásticamente el tiempo de depuración más adelante, permitiéndote concentrarte en la lógica de tu script en lugar de los detalles de parsing de Bash.
Próximos pasos
Si quieres profundizar, considera explorar:
- Funciones de shell: Cómo pasar valores entre scripts.
- Arrays: Almacenar múltiples valores en una sola variable.
- Exportar variables: Hacer que estén disponibles en shells hijos (por ejemplo, con
export). - Usar
declare: Para depurar y establecer atributos de variables. - Scripts de shell avanzados: Comprender
set -e,set -u, yset -o pipefailpara un scripting más robusto.
Con una base sólida en el quoting de variables, estás listo para abordar estos temas con confianza.
¡Feliz scripting! Si tenés algún script en Bash que haya mostrado un comportamiento extraño, no dudes en compartirlo; a menudo el problema se reduce a el quoting adecuado de variables.*
DUGLAS MORENO
Comentarios (0)
Sé el primero en comentar.