opscape

Parameter expansion cheat sheet

Every ${...} form in bash on one printable page, defaults, lengths, substrings, trimming, replacement, case and indirection, with real output.

Parameter expansion transforms a variable's value inside the shell, with no extra process. Patterns in the trimming and replacement forms are globs, not regular expressions. Forms with a colon (:-, :=, :?, :+) treat an empty value like an unset one; without the colon, only unset counts. Full explanations are in the parameter expansion guide.

Defaults and required values

v=; echo "${v:-fallback}"
Use a default when v is unset or empty; v itself is unchanged.fallback
v=; echo "[${v-fallback}]"
Use a default only when v is unset; an empty v stays empty.[]
unset v; echo "${v:=fallback}, now v=$v"
Assign the default to v when it is unset or empty, then expand to it.fallback, now v=fallback
: "${OUT_DIR:=./out}"
Set a default for a variable without doing anything else (: is the no-op command).
unset v; echo "${v:?v is required}"
Print an error and exit the (non-interactive) shell when v is unset or empty./bin/bash: line 1: v: v is required
v=1; echo "flags: ${v:+--verbose}"
Expand to the word only when v is set and non-empty; otherwise to nothing.flags: --verbose
${1:-default}
Default for a script or function argument.

Length and substrings

v=hello; echo "${#v}"
Length of the value in characters.5
v=2026-03-14; echo "${v:5}"
Substring from offset 5 (0-based) to the end.03-14
v=2026-03-14; echo "${v:5:2}"
Substring of length 2 starting at offset 5.03
v=2026-03-14; echo "${v: -2}"
Last two characters. The space before - is required; ${v:-2} is the default operator.14
v=2026-03-14; echo "${v:0:-3}"
A negative length stops that many characters before the end.2026-03

Remove a prefix or suffix

p=/var/log/app.log.gz; echo "${p#*/}"
Remove the shortest match of the pattern from the start.var/log/app.log.gz
p=/var/log/app.log.gz; echo "${p##*/}"
Remove the longest match from the start (here, like basename).app.log.gz
p=/var/log/app.log.gz; echo "${p%.*}"
Remove the shortest match from the end (drop the last extension)./var/log/app.log
p=/var/log/app.log.gz; echo "${p%%.*}"
Remove the longest match from the end (drop every extension)./var/log/app
p=/var/log/app.log.gz; echo "${p%/*}"
Remove the last slash and what follows (like dirname, for paths with a slash)./var/log

Search and replace

v=a-b-c; echo "${v/-/+}"
Replace the first match.a+b-c
v=a-b-c; echo "${v//-/+}"
Replace every match.a+b+c
v=a-b-c; echo "${v//-}"
Delete every match (empty replacement).abc
v=test.txt.txt; echo "${v/#test/prod} ${v/%.txt/.md}"
/# matches only at the start, /% only at the end.prod.txt.txt test.txt.md
v="a b c"; echo "${v// /_}"
Replace spaces with underscores.a_b_c

Case conversion (bash 4+)

v=hello; echo "${v^^}"
Uppercase the whole value.HELLO
v=HELLO; echo "${v,,}"
Lowercase the whole value.hello
v=alice; echo "${v^}"
Uppercase the first character.Alice
v=Alice; echo "${v,}"
Lowercase the first character.alice

Indirection, names and transformations

db_host=db01; key=db_host; echo "${!key}"
Expand the variable whose name is stored in key.db01
db_host=x db_port=y; echo "${!db_@}"
List the names of all variables starting with a prefix.db_host db_port
v="it's 5 * 2"; echo "${v@Q}"
Quote the value so it can be reused as shell input (bash 4.4+).'it'\''s 5 * 2'
v=hello; echo "${v@U}"
Uppercase transformation, like ^^ (bash 5.1+). @L lowercases.HELLO
declare -i n=5; echo "${n@a}"
Print the variable's attribute flags (here i for integer).i

Arrays and positional parameters

a=(x y z); echo "${#a[@]}"
Number of elements.3
a=(x y z); echo "${!a[@]}"
The indexes (or keys of an associative array).0 1 2
a=(a b c d e); echo "${a[@]:1:3}"
Slice of 3 elements starting at index 1.b c d
a=(x.txt y.txt); echo "${a[@]%.txt}"
Apply any operator to every element.x y
set -- one two three; echo "$# args, last: ${!#}, from 2: ${@:2}"
Count, last argument and a slice of the positional parameters.3 args, last: three, from 2: two three