DEV Community

Cover image for Bash Parameter Expansion Forms You Will Actually Use
Schiff Heimlich
Schiff Heimlich

Posted on

Bash Parameter Expansion Forms You Will Actually Use

You know the basics: ${var:-default} gives you a fallback. ${var:=default} assigns it. Fine. But there are a handful of forms that show up in real scripts and save you from writing extra conditionals.

The Ones Worth Remembering

${var@Q} — shell-quote the value

This is the one I reach for when passing arguments through SSH or building command strings that need to survive parsing.

cmd="docker run --rm alpine echo ${msg@Q}"
ssh host "$cmd"
Enter fullscreen mode Exit fullscreen mode

Without @Q, a message like hello world becomes two arguments. With it, you get 'hello world' — single argument, preserved.

${arr[@]@Q} — quote every array element

Same idea, but for arrays. Invaluable when you're forwarding a command with its arguments:

run_remote() {
    local cmd=("$@")
    ssh host "${cmd[@]@Q}"
}

run_remote docker run --rm alpine echo "hello world"
Enter fullscreen mode Exit fullscreen mode

Each element gets quoted individually. The remote shell sees exactly what you passed.

${var@P} — prompt expansion

Expands prompt escape sequences. Useful if you're generating PS1-style strings programmatically:

prompt="\u@\h:\w\$ "
echo "${prompt@P}"
# saiki@server:/home/saiki$ 
Enter fullscreen mode Exit fullscreen mode

Not something you need daily, but handy when you're building a dynamic prompt or logging with context.

The Glob Replacement Form

${var//pattern/repl} — global replace (there is also ${var/pattern/repl} for first match only)

path="/usr/local/bin:/usr/bin:/bin"
echo "${path//:/ }"
# /usr/local/bin /usr/bin /bin
Enter fullscreen mode Exit fullscreen mode

Cleaner than tr or sed for simple delimiters. Works with extended globs too if you shopt -s extglob.

The Error Form

${var:?error message} — fail with message if unset or empty

: "${DEPLOY_TARGET:?DEPLOY_TARGET not set}"
Enter fullscreen mode Exit fullscreen mode

Fails fast with your message. Better than a cryptic "unbound variable" later.

Why This Matters

These aren't clever tricks. They're standard Bash (since 4.4 for @Q/@P, earlier for the rest). Using them means fewer if blocks, fewer printf '%q' calls, fewer bugs from word-splitting surprises.

Next time you reach for a conditional to handle a default or quote a string, check if there's a parameter expansion form that does it inline. Often there is.

Top comments (0)