シェル(シェルスクリプト)の中では$で始まる特殊な変数が利用できます。これら特殊変数は、シェルスクリプトに与えられた引数を取得したり、スクリプト自体の情報にもとづき動作するために利用されます。 使える特殊変数には以下のようなものがあります。
変数名 | 概要 |
---|---|
$0 | シェルスクリプトのファイル名 |
$1~$n | シェル引数の値。$1は第1引数、$2は第2引数…。 |
$# | シェル引数の数 |
$* | 全引数リスト。"$*"のようにダブルクオートで囲むと、"$1 $2 … $n"形式。 |
$@ | 全引数リスト。"$@"のようにダブルクオートで囲むと、"$1" "$2" … "$n"形式。 |
$$ | 実行中のシェルのプロセスID。 |
$? | 最後に実行したコマンドのリターンコード(戻り値)。通常は成功していれば0 |
$- | シェルの実行オプション(setコマンドや#!/bin/bash行に付けたオプション。 |
$! | シェルが最後に実行したバックグラウンドプロセスのPID。 |
ちなみにこれらの特殊な変数は参照されるだけであり、値を代入することは許されません。
なお、$*、$@についてこれだけではよくわからないので、manページからの引用を掲載しておきます。
$*
$ :(1 から始まる) 全ての位置パラメータに展開されます。 ダブルクォートの内部で展開が行われたときは、 それぞれのパラメータを特別な変数である IFS の最初の文字で区切って並べた 1 つの単語に展開されます。つまり、 $ は "$1c$2c..." と同じです。 ここで c は変数 IFS の値の最初の文字です。 IFS が設定されていなければ、パラメータは空白で区切られます。 IFS が空文字列の場合、パラメータの間には区切り文字は入らず、 全てのパラメータは繋げられます。
$@
$@ :(1 から始まる) 全ての位置パラメータに展開されます。 ダブルクォートの内部で展開が行われたときは、 それぞれのパラメータは別々の単語に展開されます。 つまり "$@" は "$1" "$2" ... と同じです。 単語の中でダブルクォートの展開が行われるときには、 最初のパラメータの展開結果に元の単語のダブルクォートより前の部分が 結び付き、最後のパラメータの展開結果に元の単語のダブルクォートより 後の部分が結び付きます。 位置パラメータがない場合には、"$@" や $@ を展開しても無かったことになります (つまり取り除かれます)。
$0や$1~、$#、$*、$@、$$などは、引数やシェルスクリプト自身の情報を持っている特殊変数です。 次のようなシェルスクリプトを記述して各変数の意味を確認してみます。
#!/bin/bash
echo "script name \$0: "$0
echo "arg 1 \$1: "$1
echo "arg 2 \$2: "$2
echo "arg 3 \$3: "$3
echo "args count \$#: "$#
echo "args list \$@: "$@
echo "args list \$*: "$*
echo "PID \$\$: "$$
exit 0
これを実行すると以下のようになります。
$ ./self_test.sh arg1 arg2 arg3
script name $0: ./self_test.sh
arg 1 $1: arg1
arg 2 $2: arg2
arg 3 $3: arg3
args count $#: 3
args list $@: arg1 arg2 arg3
args list $*: arg1 arg2 arg3
PID $$: 3948
上から順にスクリプト自体の名前、引数(1~3)、引数の数、引数リスト、PIDが表示できています。
変数$?の中身を確認するために以下のようなスクリプトを作成します。
#!/bin/bash
mkdir test_dir
echo "last return code: "$?
mkdir test_dir
echo "last return code: "$?
# cleanup
rm -rf test_dir
exit 0
最初のmkdirは問題なく成功するためリターンコードは0を返しますが、2回目に同じ名前のディレクトリを作ろうとするため、2回目のmkdirは失敗します。 このスクリプトを実行すると以下のような結果になります。
$ ./return_code_test.sh
last return code: 0
mkdir: ディレクトリ `test_dir' を作成できません: ファイルが存在します
last return code: 1
bashの実行オプションを確認するために以下のようなスクリプトを作成します。
#!/bin/bash
echo "start options: "$-
echo "set option -i"
set -i
echo "options: "$-
echo "set option -r"
set -r
echo "options: "$-
echo "set option -x"
set -x
echo "options: "$-
exit 0
シェルの実行オプションを変更するにはsetコマンドを実行します。 これを実行すると以下のようになっています。
$ ./option_test.sh
start options: hB
set option -i
options: hiB
set option -r
options: hirB
set option -x
+ echo 'options: hirxB'
options: hirxB
+ exit 0
普通にbashを起動するとhBというオプションが含まれています。
次に-i、-r、-xとオプションを追加するごとに
hiB
hirB
hirxB
とオプションが追加されていくのがわかります。
シェルの中からバックグラウンドプロセスを起動した場合、そのプロセスのIDを知りたい場合があります。一定時間後に止めたいときとか。
$ top&
[1] 4140
$ ps aux | grep top | grep -v grep
test 4140 0.0 0.0 12780 836 pts/8 T 23:59 0:00 top
[1]+ 停止 top
まず、topコマンドをバックグラウンドで起動します。 この状態で$!の内容は以下のように確認することができます。
$ echo $!
4140
このように$!の内容(PID)にアクセスできるので、以下のように該当プロセスをkillすることなどが簡単におこなえます。
$ kill -9 $!
$ ps aux | grep top
test 4144 0.0 0.0 107444 960 pts/8 S+ 23:59 0:00 grep top
[1]+ 強制終了 top
特殊変数を利用して、このように凝ったシェルスクリプトを作成することも可能になります。知っておくとかなり便利です。