Bash Parameter Expansion Reference

All Bash parameter expansion forms with substitution, trimming and case modifiers.

Interactive, searchable reference for Bash ${} parameter expansion: default and alternate values, substring extraction, prefix/suffix removal, pattern replacement, case modification, length and indirection — each with a working example.

What is the difference between ${x:-word} and ${x-word}?

The colon form treats an unset variable and a set-but-empty variable the same way, substituting word for both. Without the colon, only a fully unset variable triggers the substitution; an empty string is kept as-is.

Bash parameter expansion

Parameter expansion is the ${...} syntax that lets Bash transform a variable’s value as it is substituted into a command — without calling external tools like sed, cut or tr. It covers default values, substring slicing, pattern-based trimming, search-and-replace, case changes, length and indirection. This page is a searchable, offline reference: filter by keyword or group, read a working example for each form, and click any pattern to copy it.

How it works

Every form is interpreted by the shell itself before the command runs. The core families are:

  • Default / alternate${var:-w}, ${var:=w}, ${var:+w}, ${var:?w} decide what to substitute when a variable is unset or null. A leading colon also treats an empty value as “null”; without it, only fully unset variables qualify.
  • Substring${var:offset:length} slices by character index (0-based); negative offsets count from the end.
  • Removal#/## strip a prefix and %/%% strip a suffix using glob patterns; the doubled form is greedy (longest match).
  • Replacement${var/pat/str} (first) and ${var//pat/str} (all), with /# and /% anchoring to the start or end.
  • Case^/^^ uppercase and ,/,, lowercase (Bash 4+).
  • Length / indirection${#var} returns length; ${!var} dereferences.

Tips and examples

Combine forms to build robust scripts. For example, to get a filename without its directory or extension:

path=/var/log/app.log
base=${path##*/}     # app.log   (strip longest leading dir)
name=${base%.*}      # app       (strip trailing extension)

Use the assign-default form to fill a config value once and reuse it:

: "${PORT:=8080}"    # PORT is now 8080 if it was unset
echo "Listening on ${PORT}"

Note that these operate on plain text, not on the filesystem — the patterns in #, % and / are shell globs, not regular expressions, so * matches any string and ? matches a single character.