変数の本質とメモリ上の挙動
シェル環境における変数は、プロセス内の一時記憶領域を指す識別子ラベルです。OS側では「キー=値」のペアとして管理され、メモリアドレスへの参照名として機能します。適切な識別子を通じてアクセスすることで、格納されたデータを参照・書き換えが可能です。
代入演算子の利用規約
Bashは動的型付けを採用しており、事前の型宣言なしに変数を初期化できます。=演算子を挟んで右側にデータを設定する際、等号の左右に空白文字(スペースやタブ)を含めてはいけません。これはトークン分割エラーを引き起こすため厳守が必要です。
# 変数名=値の形式で即時定義(Bashは全て文字列型として解釈)
app_user="taro_suzuki"
cache_ttl="3600"
debug_mode=true
引用符の種類と展開タイミング
変数を出力または評価する際、引用符の有無によってシェルが内部で行う置換処理が異なります。
- シングルクォート(' '): 中身は一切展開せず、文字通りそのまま渡します(厳密引用)。特殊文字や変数展開は無効化されます。
- ダブルクォーテーション(" "): 変数展開やコマンドサブシェルは有効化されますが、それ以外の特殊文字はそのまま保持されます(緩和引用)。
- 引用符なし: ワイルドカード展開やパス補完が行われるため、空白を含む値を扱う場合は意図せぬ展開を招きやすいです。
- コマンドサブシェル $(): コマンドラインの実行結果を取得し、別の変数や式に埋め込む際に使用します。
識別子の命名基準と安全な参照
変数名は英数字およびアンダースcore(_)のみ許可され、先頭は数字不可です。予約語との衝突を避けるため、標準ライブラリの命名規則を参考にした上で独自に設定してください。また、変数名の末尾に別の文字が続く場合、混同を防ぐために必ず波括弧で囲むことを推奨します。
# 明確な展開を保証する書き方
prefix="backup"
filename="${prefix}_daily.tar.gz" # 安全
filename="$prefix_daily.tar.gz" # $prefix_dailyとして認識されるリスクあり
スコープの階層構造
シェル変数の有効範囲は生成時の親子関係に強く依存します。
- ローカル変数: 現在のシェルセッション内でのみ生存します。呼び出されたサブシェルには自動的に伝播しません。
- エクスポート変数(環境変数):
exportコマンドにより公開することで、子プロセスや外部コマンドが引き継げるようになります。大抵のシステム設定用変数がこれに該当します。 - 関数内限定変数: スクリプト内で
localキーワードを付与することで、関数終了と同時に破棄されるスコープを作れます。
# サブシェル作成時の挙動確認
parent_scope="root_level"
export child_scope="global_level"
bash # サブシェルへ進入
echo "$parent_scope" # 表示されない(空文字)
echo "$child_scope" # global_level と出力される
exit # 親シェルへ戻る
引数受け取りと戻り値コードの監視
スクリプト実行時に入力された順序データは、デフォルトで位置パラメータとして格納されます。第1引数以降は$1, $2でアクセス可能であり、全引数は$@、総数は$#で把握できます。
また、直前に実行したコマンドの成否を判定するために$?変数が利用されます。正常終了時は0、異常検知時は1〜255の整数がセットされます。条件分岐の実装時に不可欠な指標です。
# コマンド実行後のステータス確認例
ls /usr/local/bin >/dev/null 2>&1
status_code=$?
if [ $status_code -eq 0 ]; then
echo "ディレクトリアクセス成功"
else
echo "権限不足または不存在"
fi
文字列操作と変数展開の応用
単一引用符と二重引用符の使い分けは、スクリプトの堅牢性を左右します。ファイルパスや日本語含むデータを取り扱う場合、特に注意が必要です。以下のパターンで挙動を整理しておきましょう。
greeting="hello"
target="world"
echo "${greeting} ${target}" # hello world (変数展開あり)
echo '${greeting} ${target}' # ${greeting} ${target} (そのまま出力)