Entrada y salida: read, echo, printf, here-doc
Introducción
Los scripts interactúan con el usuario y con otros programas a través de la entrada estándar, la salida
estándar y la salida de error. Dominar read, echo,
printf y los here-documents permite escribir scripts robustos y bien comunicados.
echo — Salida estándar
echo "Hola mundo"
echo "Valor de HOME: $HOME"
# -n: no añadir salto de línea al final
echo -n "Introduce tu nombre: "
# -e: interpretar secuencias de escape
echo -e "Línea 1\nLínea 2\tcon tabulador"
echo -e "\033[31mTexto en rojo\033[0m" # color ANSI
# Redirigir a stderr (para mensajes de error)
echo "Error: fichero no encontrado" >&2
Nota: el comportamiento de echo varía entre shells y sistemas. Para salida formateada
fiable, usar printf.
printf — Salida formateada
printf es más portable y potente que echo. Su sintaxis es similar a la del printf de C.
printf "Hola %s\n" "mundo"
printf "Nombre: %-15s Edad: %3d\n" "Juan" 30
printf "Nombre: %-15s Edad: %3d\n" "María" 25
# Salida alineada:
# Nombre: Juan Edad: 30
# Nombre: María Edad: 25
printf "%.2f\n" 3.14159 # 3.14
printf "%05d\n" 42 # 00042 (relleno con ceros)
printf "%x\n" 255 # ff (hexadecimal)
# Guardar en variable en lugar de imprimir
printf -v FECHA "%(%Y-%m-%d)T" -1 # fecha actual
Especificadores de formato:
%s→ cadena%d→ entero decimal%f→ punto flotante%x→ hexadecimal%o→ octal\n→ salto de línea\t→ tabulador%-Ns→ alineado a la izquierda en N caracteres%Nd→ entero con N dígitos mínimos
read — Leer entrada del usuario
# Leer una línea en una variable
read NOMBRE
echo "Hola, $NOMBRE"
# Con prompt (-p)
read -p "Introduce tu nombre: " NOMBRE
# Ocultar la entrada (contraseñas, -s de silent)
read -sp "Contraseña: " PASSWORD
echo # salto de línea tras la entrada oculta
echo "Contraseña recibida (longitud: {#PASSWORD})"
# Leer con timeout (-t)
if read -t 10 -p "Tienes 10 segundos para responder: " RESPUESTA; then
echo "Respondiste: $RESPUESTA"
else
echo "Tiempo agotado"
fi
# Leer en múltiples variables (divide por IFS, por defecto espacio/tab)
read -p "Introduce nombre y apellido: " NOMBRE APELLIDO
echo "Nombre: $NOMBRE, Apellido: $APELLIDO"
# Leer un solo carácter (-n)
read -n1 -p "¿Continuar? [s/n]: " RESP
echo
[[ "$RESP" =~ ^[sS]$ ]] && echo "Continuando..." || echo "Cancelado"
Leer fichero línea a línea:
# IFS= preserva los espacios iniciales y finales
# -r evita interpretar backslashes
while IFS= read -r linea; do
echo "Procesando: $linea"
done < /etc/hosts
Here-document (here-doc)
Un here-doc permite pasar un bloque de texto multilínea a un comando, como si fuera un fichero. Es muy útil para generar ficheros de configuración, enviar correos o pasar SQL a una base de datos.
Sintaxis básica:
cat <<EOF
Esta es la primera línea.
El valor de HOME es: $HOME
Hoy es: $(date +%F)
EOF
Sin expansión de variables (heredoc literal):
# Entrecomillar el delimitador para evitar expansiones
cat <<'EOF'
Esto es literal: $HOME no se expande
Y tampoco $(date)
EOF
Con indentación (heredoc con guión):
# El - permite indentar el contenido con tabuladores
cat <<-EOF
Esta línea tiene un tabulador al principio
que será eliminado en la salida
EOF
Generar un fichero de configuración:
#!/usr/bin/env bash
SERVIDOR="web01"
PUERTO=8080
cat > /etc/mi_app.conf <<EOF
# Configuración generada automáticamente el $(date)
servidor=$SERVIDOR
puerto=$PUERTO
log=/var/log/mi_app.log
EOF
echo "Configuración generada en /etc/mi_app.conf"
Here-string (cadena simple):
# Pasar una cadena como stdin sin pipe
grep "root" <<< "root:x:0:0:root:/root:/bin/bash"
# Útil para evitar el pipe en casos simples
read PRIMERO SEGUNDO <<< "hola mundo"
echo "$PRIMERO" # hola
echo "$SEGUNDO" # mundo