Skip to content
printf and Heredocs
step 1/5

Reading — step 1 of 5

Learn

~3 min readStrings and Output

printf and Heredocs

echo got you this far, and now it's time to meet its limits — and the two tools that replace it when output gets serious: printf for formatted lines, heredocs for blocks. Between them, they cover every "produce exactly this text" job a script will ever have.

echo's dirty secret

echo is fine until it isn't: its behavior with flags and escapes differs between systems and shells (echo -n, echo -e — sometimes flags, sometimes printed literally; a portability mess with decades of history). And it can't format: no padding, no decimal control, no zero-fill. The professional default in scripts that matter is:

printf: C's workhorse, shell edition

printf "Hi, %s. You're %d.\n" "$name" "$age"

Same format-string idea as C/Go (this platform teaches it thrice — it's that foundational): %s string, %d integer, %% a literal percent. Two bash-specific facts to pin:

  • No automatic newline. printf "x" leaves the cursor hanging; every line you want ends in an explicit \n. (This makes printf the clean way to print without a newline, too — no echo -n portability roulette.)
  • The format recycles. Extra arguments re-run the format: printf "%s\n" a b c prints three lines. That's a genuinely useful idiom — one-per-line output of a list in a single command.

Width and precision work as in C:

printf "%5d|\n" 42        #    42|     — right-aligned, width 5
printf "%-5d|\n" 42       # 42   |     — left-aligned
printf "%05d\n" 42        # 00042      — zero-padded
printf "%.2f\n" 3.14159   # 3.14       — yes, printf CAN format decimals…

…which deserves a callout given last chapter's news: bash arithmetic can't produce floats, but printf can format float-shaped text it's handed — the missing piece when bc/awk output needs tidying.

Heredocs: multi-line output without a hundred echos

When a script needs to emit a block — usage text, a config file, a report template — the heredoc feeds literal lines as stdin:

cat << EOF
Usage: $0 [options] <file>

Processes <file> and reports totals.
Run on $(date).
EOF

<< EOF says "everything until a line containing exactly EOF is input" (the delimiter's name is convention, not keyword). Variables and command substitutions expand inside — the block above interpolates the script name and date. Two variations complete the set:

  • << 'EOF' (quoted delimiter) — expansion OFF; every $ is literal. For emitting code or configs that contain their own $variables.
  • <<- EOF — strips leading tabs, letting the block indent with your code.

Heredocs are everywhere in real operations: embedded SQL for psql, YAML for kubectl apply -f -, generated systemd units. The pattern is always the same — a program that reads stdin, fed a template from the script itself.

Your exercise: Format Output

Produce lines with specified alignment/padding/decimals — a printf format-spec drill. The method that works every time: write the target output down, then build the format string left to right, one % spec per value, checking width and alignment against the sample. If the grader shows columns lining up, count the column width in the expected output and encode it (%-10s, %6d) — don't eyeball it. printf does exactly what the format says, which means the format has to say exactly what you want; that's not a limitation, that's the tool teaching you precision.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…