bash parameter expansion チートシート — ${var:-x} を読み解く
パラメータ展開とは?
${var} のような構文が bash parameter expansion(パラメータ展開)。単なる変数の取り出しにとどまらず、デフォルト値の指定・文字列の加工・パターンマッチによる削除や置換まで幅広い操作ができる。sed や awk を呼び出さずシェル内で完結するため、スクリプトのパフォーマンス改善にも役立つ。
全構文チートシート
| 構文 | 動作 |
|---|---|
${var} |
変数の値を展開(曖昧さ回避のため {} で囲む) |
${var:-val} |
未設定または空文字なら val を返す(代入しない) |
${var:=val} |
未設定または空文字なら val を代入して返す |
${var:+val} |
セット済みかつ非空なら val を返す |
${var:?msg} |
未設定または空文字なら msg を stderr に出して終了 |
${#var} |
変数の文字列長を返す |
${var:N} |
offset N 文字目から末尾まで取得 |
${var:N:L} |
offset N 文字目から長さ L を取得 |
${var#pat} |
先頭から最短マッチを削除 |
${var##pat} |
先頭から最長マッチを削除 |
${var%pat} |
末尾から最短マッチを削除 |
${var%%pat} |
末尾から最長マッチを削除 |
${var/pat/rep} |
最初のマッチを rep に置換 |
${var//pat/rep} |
全マッチを rep に置換 |
${var/#pat/rep} |
先頭一致のみ置換 |
${var/%pat/rep} |
末尾一致のみ置換 |
${var^} |
先頭の文字を大文字に変換(Bash 4+) |
${var^^} |
全文字を大文字に変換(Bash 4+) |
${var,} |
先頭の文字を小文字に変換(Bash 4+) |
${var,,} |
全文字を小文字に変換(Bash 4+) |
デフォルト値パターン(:- / := / :+ / :?)
「未設定のとき」「セット済みのとき」で分岐する構文群。スクリプトの引数処理・環境変数の検証に頻出する。
${var:-val} — 未設定/空なら val を返す
最も使用頻度が高い。var が未設定か空文字のとき、val を返す。var への代入は発生しない。
name=${1:-"world"}
echo "Hello, ${name}!"
# 引数なし → Hello, world!
# 引数 Alice → Hello, Alice!LOG_DIR=${LOG_DIR:-/var/log/myapp}
echo "ログ出力先: ${LOG_DIR}"${var:=val} — 未設定/空なら val を代入
:- との違いは 変数に代入が発生する点。以降のコードでも var は val になる。
: ${TMPDIR:=/tmp}
echo "${TMPDIR}" # /tmp(未設定だった場合)位置パラメータ($1 等)に := は使えない。通常の変数にのみ有効。
${var:+val} — セット済みかつ非空なら val
:- の逆の動作。var がセット済みで非空のときだけ val を返す。
VERBOSE=1
msg="処理完了${VERBOSE:+ (詳細モード)}"
echo "$msg" # 処理完了 (詳細モード)
unset VERBOSE
msg="処理完了${VERBOSE:+ (詳細モード)}"
echo "$msg" # 処理完了${var:?msg} — 未設定/空なら即時エラー
必須変数の存在チェックに使う。未設定なら msg を stderr に出力してスクリプトを終了。
#!/bin/bash
set -e
DB_HOST=${DB_HOST:?"DB_HOST が設定されていません"}set -u でも未設定変数のエラーを検出できるが、:? はカスタムメッセージを出せる点で実用的。
文字列長と部分文字列抽出
${#var} — 文字列長
str="Hello, World"
echo ${#str} # 12${var:N:L} — 部分文字列
offset N から長さ L の文字列を取り出す。L を省略すると末尾まで。
str="2026-06-02"
echo ${str:0:4} # 2026(年)
echo ${str:5:2} # 06 (月)
echo ${str:8} # 02 (日)マイナスのオフセット(末尾から)は ${var: -2} のようにスペースを入れるか ${var:(-2)} と書く。${var:-2} は「未設定なら 2」の :− 展開に解釈される。
str="Hello"
echo ${str: -3} # llo(末尾3文字)パターン削除(# / ## / % / %%)
ファイルパスの加工やファイル名から拡張子を取り除くときに多用する。basename・dirname の代替として外部プロセスを起動しない点が利点。
先頭から削除(# / ##)
${var#pat}— 先頭から最短マッチを削除${var##pat}— 先頭から最長マッチを削除
path="/home/user/docs/report.txt"
echo ${path#*/} # home/user/docs/report.txt(先頭の / 一つを削除)
echo ${path##*/} # report.txt (最後の / より前をすべて削除)ファイル名取得(basename 代替):
file="/home/user/docs/report.tar.gz"
echo ${file##*/} # report.tar.gz末尾から削除(% / %%)
${var%pat}— 末尾から最短マッチを削除${var%%pat}— 末尾から最長マッチを削除
file="report.tar.gz"
echo ${file%.*} # report.tar(最後の .xxx を削除)
echo ${file%%.*} # report (最初の . 以降をすべて削除)ディレクトリ取得(dirname 代替):
path="/home/user/docs/report.txt"
echo ${path%/*} # /home/user/docsパターンには glob が使える。${var#*_} は最初の _ まで削除、${var##*_} は最後の _ まで削除。
パターン置換(/ / //)
${var/pat/rep} — 最初のマッチを置換
msg="foo bar foo"
echo ${msg/foo/baz} # baz bar foo${var//pat/rep} — 全マッチを置換
msg="foo bar foo"
echo ${msg//foo/baz} # baz bar baz先頭・末尾一致に絞った置換
str="foo-bar-foo"
echo ${str/#foo/baz} # baz-bar-foo(先頭一致のみ)
echo ${str/%foo/baz} # foo-bar-baz(末尾一致のみ)パターンは glob として扱われる。正規表現は使えない(正規表現には [[ $str =~ pattern ]] を使う)。
大文字・小文字変換(Bash 4+)
Bash 4.0 以降で使用可能。macOS のデフォルト bash(3.x)では動かないため、brew install bash または zsh で代替する。
| 構文 | 動作 | 例 |
|---|---|---|
${var^} |
先頭を大文字 | hello → Hello |
${var^^} |
全文字を大文字 | hello → HELLO |
${var,} |
先頭を小文字 | HELLO → hELLO |
${var,,} |
全文字を小文字 | HELLO → hello |
name="alice"
echo ${name^} # Alice
echo ${name^^} # ALICE実務ユースケース集
ファイル拡張子の取得・変換
file="image.png"
ext=${file##*.} # png
base=${file%.*} # image
new="${base}.webp" # image.webpスクリプト引数のデフォルト値
#!/bin/bash
ENV=${1:-production}
PORT=${2:-8080}
echo "起動: env=${ENV} port=${PORT}"必須環境変数チェック
#!/bin/bash
: ${API_KEY:?"API_KEY が未設定です。export API_KEY=... で設定してください"}
: ${DB_URL:?"DB_URL が未設定です"}URL からドメイン部分を取り出す
url="https://example.com/path/to/page"
no_proto=${url#*://} # example.com/path/to/page
domain=${no_proto%%/*} # example.comログレベルを小文字に統一
level="WARNING"
echo ${level,,} # warningスペースを _ に置換してファイル名を安全にする
filename="my report 2026.txt"
safe=${filename// /_} # my_report_2026.txt