2017-01-03 6 views
3

bash -n script.shを使用して、シェルスクリプトの構文を検証できます。しかし、私がこの機能をテストしようとしていたとき、私はこのオプションですべての構文エラーを見つけることができないことに気付きました。例えばBASHの構文デバッグモードの不具合の確認?

[email protected]:~/testenv# cat test 
#!/bin/bash 
SEND=1 
if [ "$SEND" -eq 0 ] 
     echo no 
fi 

それでは、スクリプトをテストしてみましょう:

[email protected]:~/testenv# bash -n test 
test: line 5: syntax error near unexpected token `fi' 
test: line 5: `fi' 

それは正常に動作します。ただし、ブラケットの1つを取り外すだけの場合:

[email protected]:~/testenv# cat test  
#!/bin/bash 
SEND=1 
if [ "$SEND" -eq 0 
then 
     echo no 
fi 
[email protected]:~/testenv# bash -n test 
[email protected]:~/testenv# 

何も起こりませんでした。

は、私はまた、それが「-n」説明はbashのmanページを確認:

-n    Read commands but do not execute them. This may be used to check a 
        shell script for syntax errors. This is ignored by interactive 
        shells. 

それは右の「対話型シェル」であってはならないので、それは、スクリプトファイルのですか?だから、どうやってこれが起こるの?私はあなたが道の非常に奇妙な癖に実行している推測している

+0

ご覧ください:http://www.shellcheck.net/ – Cyrus

+0

@NeilWang:有効です!人々はそれを間違って解釈する可能性があります – Inian

+0

@Inian 2番目の例では、閉じ括弧 "]"が見つかりませんでしたが、構文チェッカーは見つかりませんでした。あなた自身のボックスでそれらを実行してください、あなたはそれがエラーをスローすることがわかります。 – NeilWang

答えて

5

は、シェルは、シングル括弧条件文を実装します[コマンド、ない特殊文字です。システムの実行可能ディレクトリ(おそらく/usr/bin)を見て、このコマンドを実装する実行可能ファイルの名前は[です。あなたは

[ "$SEND" -eq 0 ] 

ような何かを書くとき、あなたは実際には4つの引数を指定してコマンド[を起動している:

  1. $SEND
  2. の値文字列-eq
  3. 文字列0
  4. 文字列]

コマンド[は、最後の引数が]であることを確認します(そうでないと奇妙に見えるため)。残りの引数を一緒にして条件を作成し、条件のテスト結果を返します。

[はコマンドなので、好きな引数を指定してそのコマンドを呼び出すのは構文エラーではありません。もちろん、末尾の]を残しておけば、エラーが発生しますが、そのエラーはコマンド、ではなく、シェルのです。つまり、エラーを取得するために実際にスクリプトを実行する必要があります。つまり、構文チェッカーには何の問題もありません。限りはbashが懸念しているとして、[は単なるコマンド名、my_custom_conditional_test、たとえば、何ら変わりあり、そしてあなたが

my_custom_conditional_test "$SEND" -eq 0 

を書くとしたら、右、これは罰金であることは明らかだろうか? Bashは同じように[を考えています。

効率性のために、bashは実際にはではありません。実行ファイル/usr/bin/[を使用してください。 [という独自の組み込み実装を備えています。しかし、人々は[がシェルに組み込まれているかどうかにかかわらず同じ方法で動作すると期待しているので、Bashのシンタックスチェッカーは独自の[特別処理を行うことはできません。末尾に]のない/usr/bin/[を呼び出す構文エラーではないため、]を使わないで組み込みの[を呼び出す構文エラーにはなりません。

[[と多少の違いはありますが(条件のテストを行いますが)、です。これはシェルによって特別な意味が与えられています。 [[は、シェル構文の特別なトークンであり、コマンドではありません。 [の代わりに[[と書いて、対応する末尾の]]を省略すると、Bashは構文エラーについて文句を言うでしょう。

+0

あなたはまさにそうです!私は決して '/'/'/'の下に '['があることは知らなかった。私の懸念を解決してくれてありがとう。 – NeilWang