シェルにおける特殊変数

ShellShellBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、シェルスクリプトにおける特殊な変数について学びます。これらの変数は、コマンドライン引数、スクリプト名、プロセスIDなど、スクリプト実行環境に関する重要な情報を提供します。これらの変数を理解することで、より柔軟で強力なシェルスクリプトを書くことができます。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL shell(("Shell")) -.-> shell/BasicSyntaxandStructureGroup(["Basic Syntax and Structure"]) shell(("Shell")) -.-> shell/VariableHandlingGroup(["Variable Handling"]) shell(("Shell")) -.-> shell/FunctionsandScopeGroup(["Functions and Scope"]) linux(("Linux")) -.-> linux/BasicSystemCommandsGroup(["Basic System Commands"]) linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) shell(("Shell")) -.-> shell/ControlFlowGroup(["Control Flow"]) linux/BasicSystemCommandsGroup -.-> linux/echo("Text Display") shell/BasicSyntaxandStructureGroup -.-> shell/shebang("Shebang") shell/BasicSyntaxandStructureGroup -.-> shell/comments("Comments") shell/VariableHandlingGroup -.-> shell/variables_usage("Variable Usage") linux/BasicFileOperationsGroup -.-> linux/touch("File Creating/Updating") linux/BasicFileOperationsGroup -.-> linux/chmod("Permission Modifying") shell/ControlFlowGroup -.-> shell/if_else("If-Else Statements") shell/ControlFlowGroup -.-> shell/for_loops("For Loops") shell/FunctionsandScopeGroup -.-> shell/func_def("Function Definition") subgraph Lab Skills linux/echo -.-> lab-388819{{"シェルにおける特殊変数"}} shell/shebang -.-> lab-388819{{"シェルにおける特殊変数"}} shell/comments -.-> lab-388819{{"シェルにおける特殊変数"}} shell/variables_usage -.-> lab-388819{{"シェルにおける特殊変数"}} linux/touch -.-> lab-388819{{"シェルにおける特殊変数"}} linux/chmod -.-> lab-388819{{"シェルにおける特殊変数"}} shell/if_else -.-> lab-388819{{"シェルにおける特殊変数"}} shell/for_loops -.-> lab-388819{{"シェルにおける特殊変数"}} shell/func_def -.-> lab-388819{{"シェルにおける特殊変数"}} end

最初のスクリプトの作成

特殊な変数の使い方を示すために、簡単なシェルスクリプトを作成してみましょう。

  1. WebIDEで端末を開きます。コマンドプロンプトが入力を待っているはずです。
  2. プロジェクトディレクトリに移動します。
cd ~/project

このコマンドは現在のディレクトリを ~/project に変更します。これはこの実験の既定の作業ディレクトリです。3. 以下のコマンドを使って、special_vars.sh という名前の新しいファイルを作成します。

touch special_vars.sh

touch コマンドは、ファイルが存在しなければ空のファイルを作成し、存在する場合はタイムスタンプを更新します。4. WebIDEエディタでファイルを開きます。画面左側のファイルエクスプローラーでファイル名をクリックすることで行えます。5. ファイルに以下の内容を追加します。

#!/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:これをシェバンと呼びます。これはシステムにこのスクリプトを解釈するためにbashを使うように指示します。
  • $0:この特殊な変数はスクリプトの名前を保持します。
  • $1$2:これらはそれぞれ最初と2番目のコマンドライン引数を表します。
  • $@:これはスクリプトに渡されたすべてのコマンドライン引数を表します。
  • $#:これはコマンドライン引数の数を示します。
  • $$:これは現在のシェルのプロセスIDを提供します。
  1. 内容を追加した後、ファイルを保存します。
  2. 端末で以下のコマンドを実行して、スクリプトを実行可能にします。
chmod +x special_vars.sh

chmod コマンドはファイルのパーミッションを変更します。+x オプションは実行権限を追加し、スクリプトを実行できるようにします。

引数付きでスクリプトを実行する

これでスクリプトを作成したので、異なる引数を使って実行して、特殊な変数がどのように動作するか見てみましょう。

  1. 引数なしでスクリプトを実行します。
./special_vars.sh

スクリプト名の前の ./ は、シェルに対して現在のディレクトリからスクリプトを探すように指示します。

以下のような出力が表示されるはずです。

Script Name:./special_vars.sh
First Argument:
Second Argument:
All Arguments:
Number of Arguments: 0
Process ID: 1234

最初と2番目の引数が空であり、引数の数が0であることに注意してください。なぜなら、引数を提供していないからです。2. 次に、いくつかの引数を使ってスクリプトを実行します。

./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を表示します。なぜなら、2つの引数を提供したからです。

プロセスID ($$) は、オペレーティングシステムによって割り当てられるため、スクリプトを実行するたびに異なる場合があります。

$? と $! を理解する

もう2つの重要な特殊な変数は $?$! です。それらの使い方を示すために、新しいスクリプトを作成しましょう。

  1. exit_status.sh という名前の新しいファイルを作成します。
touch ~/project/exit_status.sh
  1. WebIDEエディタでファイルを開き、以下の内容を追加します。
#!/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: $!"

このスクリプトを解説しましょう。

  • $? は最後に実行されたコマンドの終了ステータスを返します。0は通常成功を意味し、非ゼロの値はさまざまなエラー状況を示します。
  • $! は最後のバックグラウンドコマンドのプロセスIDを返します。
  • コマンドの末尾の & は、それをバックグラウンドで実行します。
  1. ファイルを保存して実行可能にします。
chmod +x ~/project/exit_status.sh
  1. スクリプトを実行します。
./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です。
  • 2番目の ls コマンドは失敗します(ディレクトリが存在しないため)。したがって、$? は2です(エラーを示す非ゼロの値)。
  • sleep コマンドはバックグラウンドで実行され、$! はそのプロセスIDを返します。

関数内での特殊変数の使用

特殊変数は関数内でも使用できます。これを示すために、スクリプトを作成しましょう。

  1. function_vars.sh という名前の新しいファイルを作成します。
touch ~/project/function_vars.sh
  1. WebIDEエディタでファイルを開き、以下の内容を追加します。
#!/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回呼び出します。

  1. ファイルを保存して実行可能にします。
chmod +x ~/project/function_vars.sh
  1. スクリプトを実行します。
./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$@、および $# は、関数の引数に対してもスクリプトの引数と同じように機能します。
  • これらの変数の値は、関数に異なる引数で呼び出されるたびに変化します。

$@ と $* の違いを理解する

特殊変数 $@$* は両方ともすべてのコマンドライン引数を表すために使用されますが、二重引用符で囲まれた場合の挙動が異なります。この違いを示すために、スクリプトを作成しましょう。

  1. at_vs_star.sh という名前の新しいファイルを作成します。
touch ~/project/at_vs_star.sh
  1. WebIDEエディタでファイルを開き、以下の内容を追加します。
#!/bin/bash

echo "Using \$@:"
for arg in "$@"; do
  echo "Argument: $arg"
done

echo "Using \$*:"
for arg in "$*"; do
  echo "Argument: $arg"
done

このスクリプトは、ループ内で使用される場合の $@$* の違いを示しています。

  1. ファイルを保存して実行可能にします。
chmod +x ~/project/at_vs_star.sh
  1. 複数の引数(スペースを含むものもあり)を使ってスクリプトを実行します。
./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(Internal Field Separator)変数の最初の文字で区切られた単一の文字列に結合されます。

この違いは、スペースやその他の特殊文字を含む可能性のある引数を処理する必要がある場合に重要です。

まとめ

この実験では、シェルスクリプトにおける特殊変数とそれらを効果的に使用する方法について学びました。$0$1$@$#$$$?$! などのさまざまな特殊変数の使用方法を示すスクリプトを作成しました。また、これらの変数が関数内やコマンドライン引数を処理する際など、異なるコンテキストでどのように振る舞うかを調べました。

要点:

  1. $0$1$2 などは、スクリプト名とコマンドライン引数を表します。
  2. $@$# を使うと、すべての引数を扱い、その数を数えることができます。
  3. $$ は現在のプロセスIDを返し、一意の一時ファイルを作成する際に便利です。
  4. $? を使うと、前のコマンドが成功したかどうかを確認できます。
  5. $! は最後のバックグラウンドプロセスのPIDを返し、ジョブコントロールに便利です。
  6. $@$* は引用符で囲んだ場合の挙動が異なり、スペースを含む引数を処理する際に重要です。

これらの特殊変数を理解することは、より高度で柔軟なシェルスクリプトを書くために重要です。これらを使うことで、異なる入力に対応でき、スクリプトの実行環境に関する貴重な情報を提供できるスクリプトを作成できます。

シェルスクリプトの練習と実験を続けるうちに、これらの特殊変数を仕事で活用するさまざまな方法が見つかるでしょう。これらやその他の特殊変数に関する詳細な情報については、bashマニュアル(man bash)を参照してください。