ファイル上の現在の行番号を Bash のスクリプト内で取得したい。
例えば Perl や PHP の「__LINE__
」や Golang の _, _, line, _ := runtime.Caller(0)
のように。
他の言語では実行行の取得は分かっていたのですが、「シェルの場合は何だっけ」と Qiita 記事に絞って「site:qiita.com シェル 現在の実行行 行番号 取得
」とググってもすぐに見つからなかったので、自分のググラビリティとして。
TL; DR (今北産業)
- シェル変数の「
$LINENO
」を使う。ラインナンバーの略。 - 関数の「呼び出し元の実行行」を取得したい場合は「
$BASH_LINENO
」 - 動くサンプルをおくれ。
#!/bin/bash
echo $LINENO
echo $LINENO
$ ./sample_lineno.sh
3
4
#!/bin/bash
hoge () {
echo "Called from line:${BASH_LINENO[0]}"
}
hoge
hoge
$ ./sample_bash_lineno.sh
Called from line:7
Called from line:8
- オンラインで色々な動作を見る @ paiza.IO
動作確認済み環境
- macOS HighSierra(OSX 10.13.6)
-
bash --version
:GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
TS; DR (用途に関するコマケーこと)
実行行の取得は、一般的には LOG 出力に使うことが多いと思います。しかし、今回は終了ステータスのコードを実行行にしたかったのです。
つまり、スクリプトを exit
する際の "0
"(正常終了)以外の場合、通常はエラー番号(エラーコード)を "1
" や独自のエラーコードにするところを、「exit
した行」にしたかったのです。
#!/bin/bash
dir_curr=$(cd $(dirname $0); pwd)
# Make temp directory
# -------------------
echo -n 'Now creating temporary directory ... '
dir_temp=$(mktemp -d)
if [ $? -gt 0 ]; then
echo ' NG'
echo '* Error while creating temp directory.'; exit $LINENO
fi
echo 'OK'
# Moving to temp directory
# ------------------------
echo -n 'Now changing work directory to temporary ... '
cd $dir_temp
if [ $? -gt 0 ]; then
echo ' NG'
echo '* Error while changing work to temp directory.'; exit $LINENO
fi
echo 'OK'
exit 0
PHP や Golang などからシェル・スクリプトを外部コマンドとして実行した際、問題があった場合に標準エラー出力(STDERR
)と共に、エラー番号に意味を持たせたかったのです。
しかし、横着なため管理しきれず、「どうせソースを見に行くんだから行番号の方が楽でいいや」と**「エラー番号 = エラーで抜けた行」に統一**することにしました。_(:⁍」 )_
注意点として、bash の終了ステータス番号は1バイト、つまり 0-255 の整数です。255 を越えると 0 から再度カウントされた値が出力されます。
つまり、$EXIT_NUM % 256
と 256 で mod
(剰余) されて出力されるのです。
$ # テスト・スクリプト
$ cat sample.sh
#!/usr/bin/env bash
exit $1
$ # テスト
$ ./sample.sh 10 ; echo $?
10
$ ./sample.sh 255 ; echo $?
255
$ ./sample.sh 256 ; echo $?
0
$ ./sample.sh 257 ; echo $?
1
このように、「エラー番号=終了行」とする手法を使う場合、スクリプトは 255 行以内に抑える必要があります。偶然にも 256 行目でエラーが発生しても 0
となり正常終了扱いになったり、256 行目以降では追跡できなくなるからです。
そのため私の場合、スクリプトは 256 行以上になるならファイルをわけるという方針でカバーしています。
256 行以内に抑えることが難しい場合は、別のスクリプトにわけてメインのスクリプトから呼び出すことも可能です。
source
でスクリプトを include
しても動作する
別のスクリプト・ファイルにわける場合は、source <inclueするファイルのパス>
で可能です。その際に、include
する側は $BASH_LINENO
で「呼び出し元の行番号」を取得できます。
function function1(){
echo $BASH_LINENO
}
#!/bin/bash
source sample1.sh
function1
./Main.sh
4
- オンラインで色々な動作を見る @ paiza.IO