Bash シェルスクリプトで、コマンドライン引数を後方から参照する

Bash

はじめに

Bash シェルスクリプトでは、 コマンドライン引数は "${1}""${2}""${3}" といった特殊な変数で参照 できます。

さてここで、配列の要素を先頭ではなく 末尾から参照したい としましょう。

コマンドライン引数の個数がわかっている場合、例えば 3 個である場合には "${3}" を参照すれば良いですね。

しかしコマンドライン引数の個数が可変であった場合には、どうしたら良いでしょうか?

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ head -n 2 /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

${@: -1} と記述すれば OK

2021-06-30 13:30 に追記しました。

いろいろ書きましたが、Twitter 上でもっとかんたんに記述できることを教えていただきました。
ありがとうございます。

main.sh というスクリプトを作って実行してみます。

# スクリプトを作成
$ cat <<'EOF' >main.sh
#!/usr/bin/env bash

echo "${@: -1}"
EOF

$ chmod 700 main.sh

# 実行( 一番最後の引数が出力されます )
$ ./main.sh 1 3 5 7 9
9

一見わかりにくい記述ですので段階を追って説明しましょう。

${@: -1} ってどういう意味?

まず ${@} という変数ですが、こちらはコマンドライン引数全体を表す配列となっています。

少し変わった配列で、各要素は以下のようになっています。

  • 0 番目の要素 : スクリプト名
  • 1 番目の要素 : 1 つ目のコマンドライン引数
  • 2 番目の要素 : 2 つ目のコマンドライン引数
  • 3 番目の要素 : 3 つ目のコマンドライン引数

※何故他の言語のように添字が 0 から始まっていないのか?について、以下のエントリが参考になります。

さて、配列ということは配列の部分要素を取り出す以下の構文が利用できます。

  • ${array:offset:length}

これは array という変数の offset 番目の要素(0 が先頭)から、 length 要素取り出す という構文です。

今回は ${@} 変数の -1 番目の要素(配列の最初の添字 0 の更に前を指定すると、循環して末尾となる)から 、 1 文字取り出す という操作をすればよいわけです。

したがって

"${@: -1:1}"

となるわけですね。

ここで length を省略した場合は配列の末尾までが対象となるため、

"${@: -1}"

でコマンドライン引数の最後の要素が取得できるわけです。

末尾から 2 つ目の要素の場合は

"${@: -2:1}"

で参照できます。
この場合は、:1 の記述は必須となります。


${@:$#} と記述すれば OK

2021-06-30 13:30 に追記しました。

ここから下はもう参考にしないほうが良いかもしれません。

結論からいうと、 ${@:$#} という記述をすれば OK です。

main.sh というスクリプトを作って実行してみます。

# スクリプトを作成
$ cat <<'EOF' >main.sh
#!/usr/bin/env bash

echo "${@:$#}"
EOF

$ chmod 700 main.sh

# 実行( 一番最後の引数が出力されます )
$ ./main.sh 1 3 5 7 9
9

ひとこと

ではコマンドライン引数の最後だけを取得して何か行うようなケースが有るのか?
というと、出会ったことが有りません。

ソートされている値から 2 分探索するとかでしょうか?

Bash