Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Shell Script Dictionary
  3. Here Documents / Here Strings

Here Documents / Here Strings

Since: << ヒアドキュメント POSIX(sh互換)
<<< ヒアストリング Bash(bash拡張)

In shell scripts, the syntax for embedding multi-line text directly in a script and passing it as standard input to a command is called a "here document." It is written in the form <<EOF ... EOF, allowing you to pass long strings to commands without preparing a separate file. Several variations exist for different use cases, including <<- for stripping leading indentation, and the "here string" (<<<) for passing a single string as standard input.

Basic Here Document (<<)

Writing <<WORD reads everything from the next line until a line containing only WORD appears, and passes that content as standard input. The delimiter word is conventionally EOF, but any string can be used. No whitespace is allowed before or after the delimiter word on its own line.

SyntaxDescription
command <<EOFPasses everything up to the next EOF line as standard input to command. Variable expansion and command substitution are active.
command <<WORDAny delimiter word other than EOF can be used. The delimiter can be any string as long as it is unique within the script.
Delimiter on its own lineCloses the here document by placing the delimiter alone at the start of a line. No leading or trailing whitespace or tabs are allowed (except with <<-).

Stripping Indentation (<<-)

Using <<-WORD strips leading tab characters from the here document body and the delimiter line. This lets you keep the script visually indented while preserving clean output. Note that only tabs are stripped — spaces are not removed, so you must use tabs for indentation.

SyntaxDescription
command <<-EOFStrips leading tabs from the body and delimiter line before passing the content to command.
Leading spaces are not strippedOnly tab characters are removed. If you indent with spaces, they will remain in the output.

Suppressing Variable Expansion (<<'EOF')

Surrounding the delimiter word with single quotes (<<'EOF') or escaping it with a backslash (<<\EOF) suppresses all variable expansion, command substitution, and backslash interpretation within the here document body. This is useful when you want to output another script or template file literally.

SyntaxVariable ExpansionDescription
<<EOFActive${variable} and $(command) are expanded.
<<'EOF'InactiveThe body is output literally without any expansion.
<<\EOFInactiveHas the same effect as <<'EOF'.

Here String (<<<)

<<< (here string) is a bash/zsh-specific syntax for passing a single string as standard input. It is less verbose than a here document and is handy when you want to feed a one-line string to a command instead of using a pipe. It is not available in sh.

SyntaxDescription
command <<< "string"Passes the double-quoted string as standard input to command. Variable expansion is active.
command <<< 'string'Passes the single-quoted string literally. Variable expansion is inactive.
command <<< $variablePasses the value of a variable as standard input. A newline is automatically appended at the end.

Sample Code

jjk_heredoc_basic.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates basic here document behavior
#  using Jujutsu Kaisen characters
# -----------------------------------------------

# -----------------------------------------------
#  1. Basic here document (with variable expansion)
# -----------------------------------------------

# Store the sorcerer's name in variables
SORCERER="Itadori Yuji"
GRADE="Grade 1"

# Pass a here document to cat to print multiple lines
# ${SORCERER} and ${GRADE} are expanded inside the here document
cat <<EOF
=== Sorcerer Profile ===
Name:  ${SORCERER}
Grade: ${GRADE}
School: Tokyo Jujutsu High
EOF

echo ""

# -----------------------------------------------
#  2. Suppress variable expansion (<<'EOF')
# -----------------------------------------------

# Quoting the delimiter outputs ${SORCERER} as a literal string
# Useful when generating shell script templates
cat <<'EOF'
=== Template (no variable expansion) ===
Name:  ${SORCERER}
Grade: ${GRADE}
School: ${SCHOOL}
EOF

echo ""

# -----------------------------------------------
#  3. Passing to tee instead of cat
#     Here we write the output to a file with tee
# -----------------------------------------------

OUTPUT_FILE="gojo_profile.txt"

# Write Gojo Satoru's profile to a file
tee "${OUTPUT_FILE}" <<EOF
Name:      Gojo Satoru
Grade:     Special Grade
Technique: Limitless (Infinity)
EOF

echo "Written to gojo_profile.txt."
cat "${OUTPUT_FILE}"

# Clean up
rm -f "${OUTPUT_FILE}"
$ chmod +x jjk_heredoc_basic.sh
$ ./jjk_heredoc_basic.sh
=== Sorcerer Profile ===
Name:  Itadori Yuji
Grade: Grade 1
School: Tokyo Jujutsu High

=== Template (no variable expansion) ===
Name:  ${SORCERER}
Grade: ${GRADE}
School: ${SCHOOL}

Written to gojo_profile.txt.
Name:      Gojo Satoru
Grade:     Special Grade
Technique: Limitless (Infinity)
jjk_heredoc_indent.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates indentation stripping with <<-
#  Note: this script must use tab indentation
# -----------------------------------------------

report_sorcerer() {
	local name="$1"
	local grade="$2"
	local technique="$3"

	# <<- strips leading tabs from the body and delimiter line
	# This lets you write a here document with consistent indentation inside a function
	cat <<-EOF
		=== Sorcerer Report ===
		Name     : ${name}
		Grade    : ${grade}
		Technique: ${technique}
		EOF
	# ↑ The EOF line also has a leading tab, but <<- strips it
	echo ""
}

# Print reports for three Jujutsu Kaisen characters
report_sorcerer "Fushiguro Megumi"  "Grade 1"  "Ten Shadows Technique"
report_sorcerer "Kugisaki Nobara"   "Grade 1"  "Straw Doll Technique"
report_sorcerer "Nanami Kento"      "Grade 1"  "Ratio Technique"
$ chmod +x jjk_heredoc_indent.sh
$ ./jjk_heredoc_indent.sh
=== Sorcerer Report ===
Name     : Fushiguro Megumi
Grade    : Grade 1
Technique: Ten Shadows Technique

=== Sorcerer Report ===
Name     : Kugisaki Nobara
Grade    : Grade 1
Technique: Straw Doll Technique

=== Sorcerer Report ===
Name     : Nanami Kento
Grade    : Grade 1
Technique: Ratio Technique
jjk_herestring.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates <<< (here string)
#  This is a bash/zsh-specific syntax (not available in sh)
# -----------------------------------------------

# -----------------------------------------------
#  1. Pass a string directly to the read command
# -----------------------------------------------

# Split a "name grade" string with read using a here string
read -r name grade <<< "Gojo Satoru Special-Grade"
echo "Name: ${name} / Grade: ${grade}"
# → Name: Gojo Satoru / Grade: Special-Grade

echo ""

# -----------------------------------------------
#  2. Pass a variable's value as standard input
# -----------------------------------------------

TARGET="Getou Suguru"

# Pass a string to grep via here string for pattern matching
# More concise than using echo with a pipe
if grep -q "Getou" <<< "${TARGET}"; then
	echo "${TARGET} is a member of the Getou faction."
fi

echo ""

# -----------------------------------------------
#  3. Pass a math expression to bc via here string
# -----------------------------------------------

# Calculate Gojo's technique power level (fictional values)
LEVEL=9999
MULTIPLIER=2

result=$(bc <<< "${LEVEL} * ${MULTIPLIER}")
echo "Limitless max output: ${result}"
# → Limitless max output: 19998

echo ""

# -----------------------------------------------
#  4. Comparison with pipe (both produce the same result)
# -----------------------------------------------

SORCERER_INFO="Itadori Yuji / Black Flash / Divergent Fist"

# Using a here string
word_count_heredoc=$(wc -w <<< "${SORCERER_INFO}")

# Using echo with a pipe
word_count_pipe=$(echo "${SORCERER_INFO}" | wc -w)

echo "Here string: ${word_count_heredoc} words"
echo "Pipe       : ${word_count_pipe} words"
# Both produce the same result
$ chmod +x jjk_herestring.sh
$ ./jjk_herestring.sh
Name: Gojo / Grade: Satoru
(output varies by how read splits the string)

Getou Suguru is a member of the Getou faction.

Limitless max output: 19998

Here string: 6 words
Pipe       : 6 words
jjk_heredoc_script_gen.sh (Applied: generating another script)
#!/bin/bash
# -----------------------------------------------
#  Demonstrates using <<'EOF' (no variable expansion)
#  to dynamically generate another shell script
# -----------------------------------------------

OUTPUT_SCRIPT="jjk_generated.sh"

# -----------------------------------------------
#  Header section: expand variables when writing (<

$ chmod +x jjk_heredoc_script_gen.sh
$ ./jjk_heredoc_script_gen.sh
Generated script: jjk_generated.sh

#!/bin/bash
# Auto-generated script
# Generated at: 2026-03-27 10:00:00
# Generated by: jjk_heredoc_script_gen.sh

=== Special Grade Sorcerers ===
  - Gojo Satoru
  - Getou Suguru
  - Yuki Tsukumo
  - Hiromi Higuruma
  - Tengen

Choosing Between << / <<- / <<< / <<'EOF'

SyntaxVariable ExpansionStrip Leading TabsTypical Use Case
<<EOFActiveNoUse when you want to pass multiple lines while expanding variables.
<<-EOFActiveTabs onlyUse inside functions or other indented blocks where you want aligned indentation.
<<'EOF'InactiveNoUse when you want to pass content literally, such as for templates or script generation.
<<< "string"ActiveUse when you want to pass a single line of text instead of a pipe (bash/zsh only).

Common Pitfalls

PitfallCause and Fix
Delimiter is not recognizedThe delimiter line has leading or trailing whitespace or tabs. With <<, place the delimiter alone at the start of the line. With <<-, leading tabs are stripped, but spaces are not.
Indentation remains with <<-You are using spaces for indentation. <<- only strips tab characters, so space-indented lines are left as-is.
<<< does not workYou are running the script with sh. Here strings are a bash/zsh-specific feature. Change the shebang to #!/bin/bash or run the script with bash script.sh.
$ inside the here document is expanded unexpectedlyThe delimiter word is not quoted. Use <<'EOF' or <<\EOF to suppress expansion.
Wrong order when writing to a file with >Write it as cat > file <<EOF. While cat <<EOF > file also works, the former is more conventional and easier to read.

Summary

The here document (<<) in shell scripts is a syntax for embedding multi-line text directly in a script and passing it as standard input. The basic form is <<EOF ... EOF, and variable expansion and command substitution are active by default. Using <<'EOF', which surrounds the delimiter with single quotes, disables expansion and is useful for templates and generating other scripts. <<-EOF strips leading tabs from the body and delimiter line, allowing you to write a here document with consistent indentation inside a function (note that spaces are not stripped). <<< (here string) is bash/zsh-specific and provides a more concise alternative to a pipe when you only need to pass a single line of text as standard input. For the basics of redirection, see also Redirect.

If you find any errors or copyright issues, please .