Bash Parameter Expansion
A cheat sheet of bash parameter expansion: defaults, required variables, length, prefix and suffix removal, search and replace, substrings, case conversion, indirection and special parameters.
Free · No sign-up · Your inputs stay in your browser
Reference
Bash parameter expansion
| Syntax | Gives | Example and notes |
|---|---|---|
| ${var:-default} | var, or default if unset or empty | ${var-default} only when unset. |
| ${var:=default} | Same, and assign default to var | |
| ${var:?message} | Exit with message if unset or empty | Guards required arguments: ${1:?usage: deploy ENV}. |
| ${var:+other} | other if var is set, else nothing | Adds a flag only when needed: ${DEBUG:+--verbose}. |
| ${#var} | Length of the value | ${#arr[@]} is the number of array elements. |
| ${var#pattern} | Remove the shortest match from the start | ${path#*/} |
| ${var##pattern} | Remove the longest match from the start | ${path##*/} is basename. |
| ${var%pattern} | Remove the shortest match from the end | ${file%.*} drops the extension; ${path%/*} is dirname. |
| ${var%%pattern} | Remove the longest match from the end | ${version%%.*} is the major version. |
| ${var/old/new} | Replace the first match | |
| ${var//old/new} | Replace every match | ${PATH//:/$'\n'} prints PATH one entry per line. |
| ${var/#old/new} ${var/%old/new} | Replace only at the start, or the end | |
| ${var:offset:length} | Substring | ${var: -4} takes the last four (the space matters). |
| ${var^} ${var^^} | Uppercase first letter, all letters | bash 4+. |
| ${var,} ${var,,} | Lowercase first letter, all letters | bash 4+. |
| ${!name} | Indirection: the value of the variable named by name | |
| ${!prefix@} | Names of variables starting with prefix | ${!DB_@} |
| ${var@Q} | Value quoted for reuse as shell input | bash 4.4+. |
| ${arr[@]} ${arr[*]} | All elements | Quote "${arr[@]}" to keep elements with spaces intact. |
| ${!arr[@]} | All indexes or keys | |
| $(( 2 ** 10 )) | Integer arithmetic | No floats: use bc or awk. |
| $? $! $$ | Last exit status, last background PID, this shell's PID | |
| $# $@ $0 | Argument count, all arguments, script name | "$@" keeps each argument separate; $* joins them. |
Expansions run inside the shell, so they are faster than calling sed, basename or tr in a loop. Patterns are globs, not regular expressions. The ^ and , case operators need bash 4 or later, which macOS's /bin/bash (3.2) is not; brew install bash, or use zsh, which has its own flags.
About this tool
Method, assumptions, practical next steps, and limits.
Faster than calling tools
Expansions run inside the shell, so ${file%.*} to drop an extension or ${path##*/} for the basename is much faster in a loop than calling basename or sed thousands of times. The patterns are globs, not regular expressions. The bash manual's parameter expansion section covers each form.
Portability
Case conversion, @Q and some array forms need bash 4 or later. macOS's /bin/bash is version 3.2, so scripts that need them should require a newer bash or be written for zsh, which has its own flags.