En Bash, un «here document» (o «heredoc») redirige varias líneas de entrada a un comando o programa, como si las escribieras directamente en la terminal. Es una herramienta muy útil para incluir texto de varias líneas dentro de tus scripts sin necesidad de archivos externos ni de manipulaciones complejas de strings.
Delimitador: un heredoc comienza con el operador << seguido de una palabra delimitadora (a la que a menudo se llama «marcador» o «terminador»).
Este delimitador puede ser cualquier palabra que elijas, pero es común usar algo como EOF, END o TEXT para mayor claridad.
Para que el código sea más legible, puedes usar algo descriptivo como delimitador, por ejemplo END_INSTALLATION_INSTRUCTIONS.
Contenido: después del << DELIMITER inicial, escribes el contenido que quieres redirigir.
Puede ser varias líneas de texto, código o cualquier otra cosa.
Terminación: el heredoc termina cuando la palabra delimitadora vuelve a aparecer en una línea por sí sola, sin espacios en blanco antes ni después.
command << DELIMITER
Content line 1
Content line 2
...
Content line N
DELIMITER
<< DELIMITER inicial y el DELIMITER final.cat << EOF
This is the first line.
This is the second line.
This is the third line.
EOF
Salida:
This is the first line.
This is the second line.
This is the third line.
En este ejemplo:
cat es el comando.<< EOF inicia el heredoc con EOF como delimitador.EOF en una línea propia termina el heredoc.cat muestra el contenido que recibió.wc -l << END
Line 1
Line 2
Line 3
END
Salida:
3
Aquí, wc -l cuenta el número de líneas.
El heredoc le proporciona esas tres líneas como entrada.
El script:
#!/usr/bin/env bash
# Script to process input
while IFS= read -r line; do
echo "Processing: $line"
done
Llama al script desde un prompt interactivo de Bash con un heredoc:
./your_script << MY_DATA
Item 1
Item 2
Item 3
MY_DATA
Salida:
Processing: Item 1
Processing: Item 2
Processing: Item 3
Bash realiza expansión de variables, sustitución de comandos y expansión aritmética dentro de un heredoc. En este sentido, los heredocs se comportan como strings entre comillas dobles.
cat << EOF
The value of HOME is $HOME
The current date is $(date)
Two plus two is $((2 + 2))
EOF
Salida:
The value of HOME is /home/glennj
The current date is Thu Apr 24 13:47:32 EDT 2025
Two plus two is 4
Cuando el delimitador va entre comillas (simples o dobles), estas expansiones no se realizan. El contenido se toma de forma literal. Esto es como los strings entre comillas simples.
cat << 'EOF'
The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))
EOF
Salida:
The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))
Si usas <<- (con un guion al final) en lugar de <<, Bash eliminará los caracteres de tabulación iniciales de cada línea del heredoc.
Esto es útil para indentar el contenido del heredoc dentro de tu script sin afectar la salida.
# Note, the leading whitespace is tab characters only, not spaces!
# The ending delimiter can have leading tabs as well.
cat <<- END
This line has 1 leading tab.
This line has a leading tab and some spaces.
This line 2 leading tabs.
END
La salida se imprime con todas las tabulaciones iniciales eliminadas:
This line has 1 leading tab.
This line has a leading tab and some spaces.
This line 2 leading tabs.
El autor no recomienda este uso. Aunque puede mejorar la legibilidad del script,
Un uso típico podría ser proporcionar un texto de ayuda:
#!/usr/bin/env bash
usage() {
cat << END_USAGE
Refresh database tables.
usage: ${0##*/} [-h|--help] [-A|--no-archive]
where: --no-archive flag will _skip_ the archive jobs
END_USAGE
}
# ... parsing command line options here ...
if [[ $flag_help == "true" ]]; then
usage
exit 0
fi
Al igual que los here documents, los here strings (o «herestrings») proporcionan entrada a un comando.
Sin embargo, mientras que los heredocs se dan como un bloque de texto, los herestrings se dan como un solo string de texto.
Los here strings usan la sintaxis <<< "text".
tr 'a-z' 'A-Z' <<< "upper case this string"
Salida:
UPPER CASE THIS STRING
A diferencia de los heredocs, no se requiere un delimitador de cierre.
Se puede usar una tubería en lugar de un here string:
echo "upper case this string" | tr 'a-z' 'A-Z'
Entonces, ¿por qué usar un here string?
Considera el caso en el que obtienes el string como salida de un cálculo que tarda mucho, y quieres pasar el resultado a dos comandos distintos. Si usas tuberías, tienes que ejecutar el cálculo dos veces:
some_long_running_calculation | first_command
some_long_running_calculation | second_command
Un enfoque más eficiente es capturar la salida del cálculo (usando sustitución de comandos) y usar here strings para proporcionar la entrada a los dos comandos siguientes:
result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"
Un ejemplo real de esto:
# initialize the output CSV file
echo "ID,VALUE" > data.csv
url='https//example.com/api/query?page=1'
while true; do
json=$( curl "$url" )
# convert the results part of the response into CSV
jq -r '.results[] | [.id, .value] | @csv' <<< "$json"
# get the URL for the next page
url=$( jq -r '.next_url // ""' <<< "$json" )
if [[ "$url" == "" ]]; then
break
fi
done >> data.csv
Fíjate en la posición de la redirección de la salida.
Toda la salida del bucle while se agregará al archivo data.csv.
Como no son más que formas de redirección, se pueden combinar con otras operaciones de redirección:
cat <<< END_OF_TEXT > output.txt
This is my important text.
END_OF_TEXT
awk '...' <<< "$my_var" >> result.csv
Los here documents (o «heredocs») son una forma flexible y cómoda de manejar entradas de varias líneas en scripts de Bash. Simplifican el proceso de incluir texto y datos directamente en tus scripts, lo que los hace más autónomos y más fáciles de leer.
Los here strings (o «herestrings») son como los here documents, pero ofrecen una sintaxis más simple y dinámica.