概要
本記事では、Bashシェルで使用される全ての特殊構文・特殊変数・展開ルール・制御構文を体系的にまとめます。
変数表記について
動的・環境依存な値は <<変数名>> として表記し、全ての使用例を明示します。
| 変数名 | 例 | 説明 |
|---|---|---|
<<var>> |
name, path, user |
任意の変数名 |
<<default>> |
guest, 8080 |
デフォルト値や代替値 |
<<pattern>> |
*.txt, */ |
ファイル名や文字列パターン |
<<offset>> |
0, 3 |
部分文字列の開始位置(0始まり) |
<<length>> |
4, 10 |
部分文字列の長さ |
<<prefix>> |
ENV_, HOST |
変数名の先頭部分一致 |
<<index>> |
0, 1, 2 |
配列や連想配列のインデックス(キー) |
<<file>> |
/tmp/test.txt |
ファイルパス |
Step 1: 特殊記号(メタキャラクタ)
| 記号 | 意味 | 使用例 |
|---|---|---|
* |
任意の文字列にマッチ | ls *.txt → すべての .txt を一覧 |
? |
任意の1文字にマッチ | ls ?.sh → a.sh, b.sh など |
[a-z] |
範囲指定マッチ | ls [A-Z]* → 大文字で始まるファイル |
{a,b} |
ブレース展開 | mv {hoge,huga} |
{1..3} |
連番展開 | touch file{1..3}.txt → file1.txt file2.txt file3.txt |
$ |
変数展開 | echo $HOME |
!(否定) |
条件否定演算子 | [[ ! -f test.txt ]] → ファイルが存在しなければ真 |
!(ヒストリー展開) |
コマンド履歴展開 | !10 → 履歴番号10のコマンドを再実行 |
~ |
ホームディレクトリ展開 | cd ~ |
; |
コマンド連結 | pwd; ls |
&& |
成功時のみ実行 | make && echo OK |
| ` | ` | |
& |
バックグラウンド実行 | sleep 5 & |
| ` | ` | パイプ |
> |
標準出力リダイレクト | echo hi > out.txt |
>> |
出力を追記 | echo hi >> out.txt |
< |
標準入力を指定 | wc -l < file.txt |
() |
サブシェル実行 | (cd /tmp; ls) |
{} |
同一シェル内実行 | { echo A; echo B; } |
\ |
エスケープ | echo \$HOME |
' ' |
リテラル(展開なし) | echo '$USER' |
" " |
展開あり | echo "$USER" |
Step 2: 特殊変数
| 変数 | 内容 | 使用例 |
|---|---|---|
$0 |
スクリプト名 | echo $0 → script.sh |
$1〜$9 |
引数 | echo $1 |
$@ |
引数配列展開 | for a in "$@"; do echo $a; done |
$# |
引数の数 | echo $# |
$? |
直前の終了コード | ls /nope; echo $? |
$$ |
現在プロセスID | echo $$ |
$! |
最後のBGジョブPID | sleep 10 & echo $! |
$- |
現在のシェルオプション | echo $- |
$_ |
直前コマンドの最後の引数 | echo $_ |
$PPID |
親プロセスID | echo $PPID |
$RANDOM |
乱数0–32767 | echo $RANDOM |
$SECONDS |
シェル開始からの秒数 | echo $SECONDS |
$FUNCNAME |
関数名 | myf(){ echo $FUNCNAME; }; myf |
$PIPESTATUS[@] |
パイプ中コマンドの終了コード | `ls |
Step 3: 変数展開(Parameter Expansion)
| 構文 | 意味 | 使用例 |
|---|---|---|
${<<var>>} |
変数展開 | name=user; echo ${name} |
${<<var>>:-<<default>>} |
未定義ならdefault使用 | echo ${user:-guest} |
${<<var>>:=<<default>>} |
未定義なら代入 | echo ${port:=8080} |
${<<var>>:+alt} |
定義済みならalt使用 | x=1; echo ${x:+OK} |
${<<var>>:?msg} |
未定義ならエラー | echo ${config:?config missing} |
${#<<var>>} |
文字列長 | name=user; echo ${#name} |
${<<var>>%<<pattern>>} |
末尾最短削除 | path=/a/b/c; echo ${path%/*} → /a/b |
${<<var>>%%<<pattern>>} |
末尾最長削除 | echo ${path%%/*} → 空 |
${<<var>>#<<pattern>>} |
先頭最短削除 | echo ${path#*/} → a/b/c |
${<<var>>##<<pattern>>} |
先頭最長削除 | echo ${path##*/} → c |
${<<var>>/<<pattern>>/<<repl>>} |
最初の一致置換 | echo ${msg/foo/bar} |
${<<var>>//<<pattern>>/<<repl>>} |
全一致置換 | echo ${msg// /_} |
${<<var>>:<<offset>>} |
offsetから末尾まで | s=abcdef; echo ${s:2} → cdef |
${<<var>>:<<offset>>:<<length>>} |
offsetからlength分 | echo ${s:1:3} → bcd |
${!<<prefix>>*} |
prefixで始まる変数一覧 | HOST1=x; HOST2=y; echo ${!HOST*} |
${!<<var>>} |
間接参照 | ref=NAME; NAME=user; echo ${!ref} |
${<<var>>,} / ${<<var>>^^} |
大文字・小文字変換 | n=abc; echo ${n^^} → ABC |
${<<var>>@Q} |
引用付き展開 | x='abc'; echo ${x@Q} → 'abc' |
Step 4: 配列・連想配列
# 配列の定義と利用
arr=(a b c)
echo ${arr[<<index>>]} # 指定インデックス要素を取得
echo ${#arr[@]} # 配列要素数
for i in "${arr[@]}"; do echo $i; done
# 連想配列の定義と利用
declare -A map
map[<<index>>]=100
map[name]=user
echo ${map[<<index>>]} # 値取得
echo ${!map[@]} # すべてのキー一覧
Step 5: 算術展開
x=5
y=3
echo $((x + y)) # 8
((x *= 2))
echo $x # 10
Step 6: 条件式と比較
# 文字列
if [ "$USER" = "root" ]; then echo root; fi
# 数値
if [ "$x" -lt 10 ]; then echo "small"; fi
# ファイル
if [ -f /etc/passwd ]; then echo "exists"; fi
# 正規表現
s="hello123"
[[ $s =~ [0-9]+ ]] && echo "contains number"
Step 7: コマンド置換・サブシェル
# コマンド出力を展開
echo "Today: $(date +%Y-%m-%d)"
# サブシェル
(cd /tmp; ls)
Step 8: リダイレクト・FD操作
echo "Hello" > <<file>> # 標準出力をファイルに
echo "Append" >> <<file>> # 追記
wc -l < <<file>> # 標準入力として使う
ls /notfound 2> err.log # 標準エラー出力をファイルへ
echo "OK" >&2 # 標準エラー出力に送る
exec 3> custom.log # FD3を開く
echo "via fd3" >&3
exec 3>&- # FD3を閉じる
用語補足: ファイルディスクリプタ(FD)
| FD番号 | 名称 | 説明 | 使用例 |
|---|---|---|---|
0 |
標準入力(stdin) | キーボードやファイルからの入力 | < file.txt |
1 |
標準出力(stdout) | 通常の出力(端末・ファイル) | echo test > out.txt |
2 |
標準エラー出力(stderr) | エラー出力専用 | ls /nope 2> err.log |
3以降 |
任意のFD | ユーザー定義の出力ストリーム | exec 3> log.txt |
FD3 とは、ユーザーが自由に作成できる追加のファイルディスクリプタです。
例えば次のように使います:
exec 3> process.log # FD3を作成
echo "実行開始" >&3 # FD3に書き込む → process.logに出力
exec 3>&- # FD3を閉じる
Step 9: トラップとエラー制御
set -e # エラーで停止
set -u # 未定義変数をエラー扱い
set -x # 実行コマンドを表示
set -o pipefail # パイプ途中のエラー検出
trap 'echo 終了しました' EXIT
trap 'echo エラー発生' ERR
Step 10: ジョブ制御
sleep 10 & # バックグラウンドで実行(ジョブ1)
jobs # ジョブ一覧表示
fg %1 # ジョブ番号1をフォアグラウンドへ
bg %1 # ジョブ番号1をバックグラウンドへ
disown %1 # ジョブ1をシェル管理から切り離す
kill %1 # ジョブ1を終了
用語補足: ジョブ番号と %1 の意味
Bashで & をつけてコマンドを実行すると、それは「ジョブ」として管理されます。
jobs コマンドを実行すると、シェル内で実行中のジョブ一覧が表示されます。
例:
sleep 60 &
jobs
出力:
[1]+ Running sleep 60 &
[1]が ジョブ番号%1は「ジョブ番号1番を参照する記号」
| 記号 | 意味 |
|---|---|
%1 |
ジョブ番号1番のジョブ |
%+ |
現在のカレントジョブ |
%- |
直前のジョブ |
使用例:
fg %1 # ジョブ1をフォアグラウンドへ
bg %1 # ジョブ1をバックグラウンド再開
kill %1 # ジョブ1を終了
Step 11: 特殊コマンド・予約語
: # 何もしない(常に成功)
true # 成功終了
false # 失敗終了
source ~/.bashrc
eval "echo executed"
{ echo A; echo B; }
まとめ
Bashスクリプトにおける特殊構文・展開・変数・記号・制御構文を包括的に網羅しました。
これを理解すれば、任意のシェルスクリプトを正確に解析・設計でき、再利用性と安全性の高い自動化が実現できます。
