bashの特殊変数の説明を読んでもよくわからなかったので試してみた

「LinuC レベル1」の参考書の中で「bashの特殊変数」という説明があり、以下のような表が掲載されているのですが、どのような動きになるのかわからなかったので実際に試してみました。

| 変数 | 表示 |
|:-:|:-|
| $0 | スクリプトファイル名 |
| \$1,\$2...\$n | 第1引数,第2引数...第n引数 |
| $@ | すべての引数をスペースで区切って表示 |
| $* | すべての引数を$IFSで指定された値で区切って表示 |
| $# | 引数の個数 |
| $_ | 最後に実行したコマンドの最後の引数 |
| $? | 直前の処理の成否(成功:0/失敗:0以外) |
| $$ | 現在実行しているシェルのPID |
| $! | 最後に実行したバックグラウンドコマンドのPID |

- `$!` については参考書内での記載がなかったため、「LinuC レベル1」の試験範囲から外れるかもしれませんが、「[GNU Bash manual](https://www.gnu.org/software/bash/manual/)」の「[3.4.2 Special Parameters](https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html)」に記載がありましたので取り上げてみました。
- `$_` も同様に「LinuC レベル1」の試験範囲外のようですが、こちらは「[GNU Bash manual](https://www.gnu.org/software/bash/manual/)」の「[5.2 Bash Variables](https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html#Bash-Variables)」に記載があります。
- bashの引数については `man bash` 内の「ARGUMENTS」に説明があります。
- bashの特殊変数については `man bash` 内の「Special Parameters」に説明があります。

こんなシェルスクリプトを準備してみた。

```:special_variables.sh
# スクリプトファイル名を出力
echo '$0' "[this scripts name: $0]"
# 第1引数を出力
echo '$1' "[argument1: $1]"
# 第2引数を出力
echo '$2' "[argument2: $2]"
# 第3引数を出力
echo '$3' "[argument3: $3]"
# すべての引数をスペース区切りで出力
echo '$@' "[arguments: $@]"
# 区切り文字をカンマに設定
IFS=$','
# すべての引数をカンマ区切りで出力
echo '$*' "[arguments: $*]"
# 引数の個数を出力
echo '$#' "[arguments count: $#]"
# 最後の引数を「$_」で取得するためにechoに引数を渡して実行
echo arg1 arg2 arg3 arg4 arg5 >/dev/null 2>&1
# 直前のコマンドの最後の引数を出力
echo '$_' "[last argument: $_]"
# 現在実行しているシェルのPIDを出力
echo '$$' "[this scripts pid: $$]"
# 成功パターンのコマンドを実行
ls ./special_variables.sh >/dev/null 2>&1
# 直前のコマンドの処理の成否を出力（成功パターン）
echo '$?' "[last command status(success): $?]"
# 失敗パターンのコマンドを実行
ls ./special_variables.s >/dev/null 2>&1
# 直前のコマンドの処理の成否を出力（失敗パターン）
echo '$?' "[last command status(failure): $?]"
# バックグラウンドでコマンドを実行
echo "background job" &
last_background_pid="$!"
# 最後に実行したバックグラウンドコマンドのPIDを出力
echo '$!' "[last background pid: $last_background_pid]"
kill $last_background_pid
```

引数を「arg1」〜「arg5」のように5つ指定して実行してみると、以下のような結果になりました。

```
$ bash special_variables.sh arg1 arg2 arg3 arg4 arg5
$0 [this scripts name: special_variables.sh]
$1 [argument1: arg1]
$2 [argument2: arg2]
$3 [argument3: arg3]
$@ [arguments: arg1 arg2 arg3 arg4 arg5]
$* [arguments: arg1,arg2,arg3,arg4,arg5]
$# [arguments count: 5]
$_ [last argument: arg5]
$$ [this scripts pid: 7126]
$? [last command status(success): 0]
$? [last command status(failure): 2]
$! [last background pid: 7129]
```

### 参考URL
- [Shell 特殊変数](https://qiita.com/a_yasui/items/ec4f75b300410af8958d)
- [bash で利用される特殊変数](https://qiita.com/sand_bash/items/725fd04cb66bce8c495f)
- [[メモ]シェルスクリプトの特殊変数](https://qiita.com/Yorinton/items/a042fe748564745b9b0b)
- [bash変数のあれこれ](https://qiita.com/harasakih/items/f75d5dadeb028511b735)
- [bashおよびスクリプト](https://qiita.com/TA6335/items/7db16be89e27c00ff089)
- [シェルスクリプトで、受け取った引数をすべて別のコマンドに渡す](https://qiita.com/KEINOS/items/1dae545d5b83a1e000e1)
- [ShellScriptの基本](https://qiita.com/su-kun1899/items/0f5eacea2334f18ff306)
- [[Linux] 区切り文字を変更する (IFS)](https://qiita.com/Arime/items/7a542637b84fd170f305)
- [bashでのPID取得方法まとめ($$、$PPID、$!、$BASHPID)](https://qiita.com/laikuaut/items/1daa06900ad045d119b4)
- [bash サブシェルを利用してファイル名の区切り文字IFSを一時的に変更する](https://min117.hatenablog.com/entry/2020/01/03/104644)
- [mkdir と同時に cd でディレクトリ移動させるには（空白入りディレクトリ名の場合）](https://qiita.com/KEINOS/items/1da5ca6443bd7f254119)
- [Bashの$@,$#などの$から始まる特殊な変数について](https://linuxcommand.net/bash-special-parameters/)
- [直前に実行したコマンドの最後の引数を取得する方法3つ](https://tekunabe.hatenablog.jp/entry/2020/06/05/205532)