Reading — step 1 of 5
Learn
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 makesprintfthe clean way to print without a newline, too — noecho -nportability roulette.) - The format recycles. Extra arguments re-run the format:
printf "%s\n" a b cprints 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…