はじめに
この実験では、シェルスクリプトにおける特殊変数(Special Variables)について学びます。これらの変数は、コマンドライン引数、スクリプト名、プロセス ID など、スクリプトの実行環境に関する重要な情報を提供します。これらの変数を理解することで、より柔軟で強力なシェルスクリプトを作成できるようになります。
この実験では、シェルスクリプトにおける特殊変数(Special Variables)について学びます。これらの変数は、コマンドライン引数、スクリプト名、プロセス ID など、スクリプトの実行環境に関する重要な情報を提供します。これらの変数を理解することで、より柔軟で強力なシェルスクリプトを作成できるようになります。
まずは、特殊変数の使い方を確認するためのシンプルなシェルスクリプトを作成しましょう。
WebIDE のターミナルを開きます。入力待ちのコマンドプロンプトが表示されているはずです。
プロジェクトディレクトリに移動します。
cd ~/project
このコマンドは、現在のディレクトリをこの実験のデフォルト作業ディレクトリである ~/project に変更します。
special_vars.sh という名前の新しいファイルを作成します。touch special_vars.sh
touch コマンドは、ファイルが存在しない場合は空のファイルを作成し、存在する場合はタイムスタンプを更新します。
WebIDE のエディタでファイルを開きます。画面左側のファイルエクスプローラーでファイル名をクリックすると開くことができます。
ファイルに以下の内容を記述します。
#!/bin/bash
echo "Script Name: $0"
echo "First Argument: $1"
echo "Second Argument: $2"
echo "All Arguments: $@"
echo "Number of Arguments: $#"
echo "Process ID: $$"
各行の役割を解説します。
#!/bin/bash: シバン(Shebang)と呼ばれます。このスクリプトを解釈するために bash を使用することをシステムに伝えます。$0: この特殊変数にはスクリプトの名前が格納されます。$1 と $2: それぞれ、1 番目と 2 番目のコマンドライン引数を表します。$@: スクリプトに渡されたすべてのコマンドライン引数を表します。$#: コマンドライン引数の個数を示します。$$: 現在実行されているシェルのプロセス ID(PID)を示します。内容を入力したらファイルを保存します。
ターミナルで次のコマンドを実行し、スクリプトに実行権限を付与します。
chmod +x special_vars.sh
chmod コマンドはファイルの権限を変更します。+x オプションは実行権限を追加するもので、これによりスクリプトを直接実行できるようになります。
スクリプトが作成できたので、異なる引数を指定して実行し、特殊変数がどのように変化するかを確認してみましょう。
./special_vars.sh
スクリプト名の前にある ./ は、現在のディレクトリにあるスクリプトを探すようシェルに指示するものです。
以下のような出力が表示されるはずです。
Script Name: ./special_vars.sh
First Argument:
Second Argument:
All Arguments:
Number of Arguments: 0
Process ID: 1234
引数を指定していないため、1 番目と 2 番目の引数は空になり、引数の数は 0 になっていることに注目してください。
./special_vars.sh hello world
出力は以下のようになります。
Script Name: ./special_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Process ID: 1235
変化した点は以下の通りです。
$1 に "hello" が格納された$2 に "world" が格納された$@ にすべての引数 "hello world" が表示された$# が引数の数である 2 を示したプロセス ID($$)は、実行のたびにオペレーティングシステムによって割り当てられるため、実行ごとに異なる値になります。
$? と $! の理解他にも重要な特殊変数として $? と $! があります。これらを確認するための新しいスクリプトを作成しましょう。
exit_status.sh という名前の新しいファイルを作成します。touch ~/project/exit_status.sh
#!/bin/bash
echo "Running a successful command:"
ls /home
echo "Exit status: $?"
echo "Running a command that will fail:"
ls /nonexistent_directory
echo "Exit status: $?"
echo "Running a background process:"
sleep 2 &
echo "Process ID of last background command: $!"
このスクリプトの解説:
$?: 最後に実行されたコマンドの終了ステータス(Exit Status)を返します。通常、0 は成功を意味し、それ以外の値はエラーが発生したことを示します。$!: 最後にバックグラウンドで実行されたコマンドのプロセス ID を返します。& を付けると、そのコマンドをバックグラウンドで実行します。chmod +x ~/project/exit_status.sh
./exit_status.sh
以下のような出力が表示されるはずです。
Running a successful command:
labex
Exit status: 0
Running a command that will fail:
ls: cannot access '/nonexistent_directory': No such file or directory
Exit status: 2
Running a background process:
Process ID of last background command: 1236
注目ポイント:
ls コマンドは成功したため、$? は 0 になります。ls コマンドは(ディレクトリが存在しないため)失敗し、$? は 2(エラーを示す 0 以外の値)になります。sleep コマンドがバックグラウンドで実行され、$! によってそのプロセス ID が表示されます。特殊変数は関数の中でも使用できます。これを確認するスクリプトを作成しましょう。
function_vars.sh という名前の新しいファイルを作成します。touch ~/project/function_vars.sh
#!/bin/bash
function print_args {
echo "Function Name: $0"
echo "First Argument: $1"
echo "Second Argument: $2"
echo "All Arguments: $@"
echo "Number of Arguments: $#"
}
echo "Calling function with two arguments:"
print_args hello world
echo "Calling function with four arguments:"
print_args one two three four
このスクリプトでは、特殊変数を使用する print_args という関数を定義しています。その後、異なる数の引数を渡してこの関数を 2 回呼び出しています。
chmod +x ~/project/function_vars.sh
./function_vars.sh
以下のような出力が表示されるはずです。
Calling function with two arguments:
Function Name: ./function_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Calling function with four arguments:
Function Name: ./function_vars.sh
First Argument: one
Second Argument: two
All Arguments: one two three four
Number of Arguments: 4
注目ポイント:
$0 は関数名ではなく、依然としてスクリプト名を指します。$1、$2、$@、$# は、スクリプトの引数と同じように、関数の引数に対して機能します。$@ と $* の違いを理解する特殊変数 $@ と $* はどちらもすべてのコマンドライン引数を表しますが、ダブルクォーテーションで囲んだ場合の挙動が異なります。この違いを確認しましょう。
at_vs_star.sh という名前の新しいファイルを作成します。touch ~/project/at_vs_star.sh
#!/bin/bash
echo "Using \$@:"
for arg in "$@"; do
echo "Argument: $arg"
done
echo "Using \$*:"
for arg in "$*"; do
echo "Argument: $arg"
done
このスクリプトは、ループ内での "$@" と "$*" の挙動の違いを示します。
chmod +x ~/project/at_vs_star.sh
./at_vs_star.sh "arg with spaces" another_arg "third arg"
以下のような出力が表示されるはずです。
Using $@:
Argument: arg with spaces
Argument: another_arg
Argument: third arg
Using $*:
Argument: arg with spaces another_arg third arg
何が起きているのか:
"$@" を使用すると、各引数は個別の要素として扱われます。スペースを含む引数も、一つの単位として正しく保持されます。"$*" を使用すると、すべての引数が一つの文字列に結合されます。各引数は IFS(内部フィールド区切り文字)変数の最初の文字(通常はスペース)で区切られます。この違いは、スペースや特殊文字を含む可能性のある引数を処理する場合に非常に重要になります。
この実験では、シェルスクリプトにおける特殊変数とその効果的な活用方法について学びました。$0、$1、$@、$#、$$、$?、$! といった様々な特殊変数を使用するスクリプトを作成しました。また、関数内での挙動や、コマンドライン引数を処理する際のコンテキストによる違いについても確認しました。
学んだポイント:
$0、$1、$2 などは、スクリプト名やコマンドライン引数を表します。$@ と $# を使うと、すべての引数を操作したり、その数を数えたりできます。$$ は現在のプロセス ID を取得でき、一意のテンポラリファイルを作成する際などに役立ちます。$? は直前のコマンドが成功したかどうかを確認するのに役立ちます。$! は最後に実行したバックグラウンドプロセスの PID を取得でき、ジョブ制御に利用できます。"$@" と "$*" はクォート時の挙動が異なり、スペースを含む引数を扱う際に重要です。これらの特殊変数を理解することは、より高度で柔軟なシェルスクリプトを書くために不可欠です。これらを利用することで、入力に応じて動作を変えたり、実行環境に関する貴重な情報を取得したりするスクリプトを作成できるようになります。
今後もシェルスクリプトの練習を続け、これらの特殊変数を活用してみてください。より詳細な情報が必要な場合は、bash のマニュアル(man bash)を参照することをお勧めします。