はじめに
こんにちは!TechBull 運営メンバーでインフラエンジニアの相川(@riv_infra)です。シェルスクリプトを読んでいて特殊変数が出てきた際にあまり馴染みがないなと感じました。そこで、特殊変数について調べて自分なりにまとめてみたことをブログにしました。初学者向けの基本的な部分からおさらいしていきたいと思います。
変数とは
変数という概念はプログラミング言語だったり、シェルにおいて利用されます。変数とは、名前(変数名)のついた箱に物(値)を入れるたとえや、物(値)にラベル(変数名)をつけるといった例えをよくされます。変数には、文字列や数値、配列など様々な型のデータを代入することができます。
シェルにおいて、変数は3種類に分かれます。
種類 | 変数名 | 説明 |
シェル変数 | 英数字とアンダースコア(_) | Exportすると環境変数になる |
位置変数(位置パラメータ) | 数字(0を除く) | 引数の受け渡しに利用 |
特殊変数(特殊パラメータ) | 記号または0 | 終了ステータスなど属性値を取得 |
【参考】 [改訂第4版]シェルスクリプト基本リファレンス 技術評論社
この中でもよく使われるのは、シェル変数になります。$HOMEや$PATHなどと聞くと初学者の方も見たことがあるのではないでしょうか。
特殊変数の例
特殊変数のいくつかの例を表にまとめてみました。直前のコマンドの終了ステータスを取得できる$?などは使われているのを見たことがあります。$@と$*は少し違いがあり、$@は全ての引数をそのまま別々で受け渡せますが、$*はそれぞれの引数が半角空白で区切られた一つの文字列として受け渡されます。そのため、$@の方が使う機会が多そうなため、注意が必要です。
変数 | 説明 |
$0 | 実行されたスクリプト名 |
$$ | 実行されたスクリプトのプロセスID |
$? | 直前のコマンドの終了ステータス |
$# | スクリプトに渡された引数の数 |
$1,$2, … | $1:第一引数 $2:第二引数 … |
$@ | すべての引数 (“$1” “$2” … のように展開される) |
$* | すべての引数 (`”$1 $2 …” のように展開される) |
$_ | 直前のコマンドの最後の引数 |
特殊変数に親しむ
特殊変数の例とその説明についてご覧いただきましたが、読むだけだと身につきづらいと思います。完全に覚える必要はないと思いますが、何かを実現したい際に「特殊変数を使えば出来そうだ」というとっかかりになるくらいには親しんでおけると良いかなと思います。そこで、思いつきでクイズを作ってみました。シェルスクリプトになっているので、興味のある方は是非お試し頂けると嬉しいです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
#!/bin/sh score=0 total_questions=6 echo "============================" echo " sh 自動変数クイズ! " echo "============================" echo "" echo "質問ごとに答えを入力してください (空欄でスキップ)" echo "----------------------------" # Q1: スクリプトのファイル名 echo "Q1: \$0" read -r answer if [[ "$answer" == "$0" ]]; then echo "✅ 正解!" ((score++)) else echo "❌ 不正解!正解: $0" fi echo "" # Q2: このプロセスのPID echo "Q2: \$$" read -r answer if [[ "$answer" == "$$" ]]; then echo "✅ 正解!" ((score++)) else echo "❌ 不正解!正解: $$" fi echo "" # Q3: 直前のコマンドの終了ステータス echo "Q3: \$?" read -r answer if [[ "$answer" == "$?" ]]; then echo "✅ 正解!" ((score++)) else echo "❌ 不正解!正解: $?" fi echo "" # Q4: 引数の数 echo "Q4: \$#" read -r answer if [[ "$answer" == "$#" ]]; then echo "✅ 正解!" ((score++)) else echo "❌ 不正解!正解: $#" fi echo "" # Q5: 第一引数 echo "Q5: \$1 は何?(なければ [なし] と入力)" read -r answer if [[ -z "$1" && "$answer" == "なし" ]] || [[ "$answer" == "$1" ]]; then echo "✅ 正解!" ((score++)) else echo "❌ 不正解!正解: ${1:-なし}" fi echo "" # Q6: すべての引数 echo "Q6: \$@ をスペース区切りで入力" read -r answer if [[ "$answer" == "$*" ]]; then echo "✅ 正解!" ((score++)) else echo "❌ 不正解!正解: \"$*\"" fi echo "" # 結果発表 echo "============================" echo " クイズ終了!" echo " 得点: $score / $total_questions" if (( score == total_questions )); then echo "🎉 完璧!sh 自動変数マスター!" elif (( score >= total_questions / 2 )); then echo "👍 よくできました!" else echo "💡 もう少し練習が必要ですね。" fi echo "============================" |
試して頂ける方は、引数を色々変えてみたり、何回か繰り返してどんな意味だったか思い出すということをしてみるとよいかもですね!
まとめ
今後も工夫して楽しく学んでいくことが出来ればいいなと思います!また、急な宣伝となりますが3/15にLT大会を実施予定です!!是非ご参加ください!
https://techbull.connpass.com/event/345494/
さてさて!3/15土曜日のお昼からふんわりさんと合同LT大会をやることになりました!!インフラからアプリケーションまでジュニアレベルのエンジニアがLTするので楽しみです!!ぜひ!👏👏
第1回 TechBullx若手ふんわり勉強部 合同LT&交流会! https://t.co/J5rvo8r3oF #TechBull_ふんわり
— TechBull☁️エンジニアコミュニティ (@techbull_cloud) February 15, 2025

1997年生まれ。未経験から派遣でサーバ運用がメインのインフラエンジニア。技術力をつけるため書籍やWebで学んだり資格取得などをするも、独学の限界を覚える。ひょんなことからMENTAを知り、その流れでTechBullに加入。課題形式が性に合っており毎日が楽しく、輪読会やもくもく会の主催リーダーとして企画している。