bash parameter expansion チートシート — ${var:-x} を読み解く

bash parameter expansion チートシート — ${var:-x} を読み解く

パラメータ展開とは?

${var} のような構文が bash parameter expansion(パラメータ展開)。単なる変数の取り出しにとどまらず、デフォルト値の指定・文字列の加工・パターンマッチによる削除や置換まで幅広い操作ができる。sedawk を呼び出さずシェル内で完結するため、スクリプトのパフォーマンス改善にも役立つ。

全構文チートシート

構文 動作
${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 を代入

:- との違いは 変数に代入が発生する点。以降のコードでも varval になる。

: ${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文字)

パターン削除(# / ## / % / %%

ファイルパスの加工やファイル名から拡張子を取り除くときに多用する。basenamedirname の代替として外部プロセスを起動しない点が利点。

先頭から削除(# / ##

  • ${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^} 先頭を大文字 helloHello
${var^^} 全文字を大文字 helloHELLO
${var,} 先頭を小文字 HELLOhELLO
${var,,} 全文字を小文字 HELLOhello
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

次に読む