En los scripts de Bash, un «here document» (o «heredoc») redirige varias líneas de entrada a un comando o programa, como si las escribieras directamente en el terminal. Es una herramienta muy potente para incrustar texto de varias líneas dentro de tus scripts sin necesidad de archivos externos ni de complejas manipulaciones de strings.
Delimitador: un heredoc empieza 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 lo habitual es usar algo como EOF, END o TEXT para mayor claridad.
Para que el código sea más legible, puedes usar como delimitador algo descriptivo, 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.
Finalización: el heredoc termina cuando la palabra delimitadora vuelve a aparecer sola en una línea, sin espacios en blanco delante ni detrá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 sola en su propia línea pone fin al heredoc.cat muestra el contenido que ha recibido.wc -l << END
Line 1
Line 2
Line 3
END
Salida:
3
Aquí, wc -l cuenta el número de líneas.
El heredoc proporciona las 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 usando 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 producen. 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 resulta útil para indentar el contenido del heredoc dentro de tu script sin afectar a 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 único 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 necesita un delimitador final.
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?
Piensa en el caso en que obtienes el string como salida de un cálculo largo, 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 entrada a los dos comandos siguientes:
result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"
Aquí tienes una aplicación real de ese ejemplo:
# 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 añadirá 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 gestionar la entrada de varias líneas en los scripts de Bash. Simplifican el proceso de incrustar texto y datos directamente en tus scripts, lo que los hace más autónomos y fáciles de leer.
Los here strings (o «herestrings») son como los here documents, pero ofrecen una sintaxis más sencilla y dinámica.