安全のために、構文エラーが発生した場合、bashはスクリプトの実行を中止します。
驚いたことに、私はこれを達成できません。 ( set -e
では不十分です。)例:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
結果(bash-3.2.39またはbash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
構文エラーをキャッチするためにすべてのステートメントの後に$?
をチェックすることはできません。
(私は賢明なプログラミング言語からそのような安全な動作を期待していました...多分これはバグ/開発者への願いとして報告する必要があります)
if
は違いがありません。if
を削除しています:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
結果:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
おそらく、それは http://mywiki.wooledge.org/BashFAQ/105 の演習2に関連しており、(( ))
と関係があります。しかし、構文エラーを続けて実行するのはまだ理不尽です。
(( ))
は違いません!算術テストがなくても動作が悪い!単純で基本的なスクリプト:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
結果:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
全体を関数にラップするのがトリックを行うようです:
#!/bin/bash -e
main () {
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
}
main "$@"
結果:
$ ./sh-on-syntax-err
$ ./sh-on-syntax-err line 6: #: syntax error: operand expected (error token is "#")
$
理由はわかりませんが、誰か他の人が説明できますか?
set -e
の真の意味について誤解している可能性があります。 help set
の出力を注意深く読むと、次のことがわかります。
-e Exit immediately if a command exits with a non-zero status.
つまり、-e
はcommandsの終了ステータスがゼロ以外であることであり、スクリプトの構文エラーではありません。
一般に、set -e
を使用することは悪い習慣と見なされます。すべてのエラー(つまり、コマンドからのゼロ以外のすべての戻り)は、スクリプトによって適切に処理される必要があるためです(堅牢なスクリプトと考えてください。スペースを含むファイル名、またはハイフンで始まるファイル名を入力してください)。
構文エラーの種類によっては、スクリプトがまったく実行されないこともあります。私はbashについて十分な知識がなく、正確にどのクラスの構文エラー(分類できる場合のみ)がスクリプトの即時中止につながるかを教えてくれません。たぶんいくつかのバッシュの教祖が参加し、すべてを明確にするでしょう。
set -e
ステートメントを明確にしたいと思います!
あなたの願いについて:
私は賢明なプログラミング言語からそのような安全な動作を期待していました...おそらくこれはバグ/開発者への要望として報告する必要があります
答えは間違いなくno!あなたが観察したこと(set -e
期待どおりに応答しない)は実際に非常によく文書化されているためです。
あなたは次のようなものを置くことによってスクリプト自体をチェックさせることができます
bash -n "$0"
スクリプトの先頭近く-set -e
の後、重要なコードの前。
これはあまり堅牢ではないと感じなければなりませんが、それがあなたのために働くなら、おそらくそれは許容できます。
まず、bashの(( ))
は算術計算として使用されます。if...では使用せず、[]
を使用します。
次に、${a[#]}
は奇妙で、エラーが発生するのはそのためです...#
には配列の意味がありません
これで何をしたいのかわかりませんが、フィールドの数を知りたいので、代わりに${#a[*]}
が必要です
最後に、整数を比較するときは、-eq
よりも==
をお勧めします(文字列に使用)。 ==
も機能しますが、-eq
をお勧めします。
あなたが望んでいるのは:
if [ ${#a[*]} -eq 2 ]; then