2013-10-30 111 views
6

開発ワークフローを合理化するためのシェルスクリプトを作成しています。「単項演算子が予想される」エラーが発生するのはなぜですか?

私はどのテーマフォルダに関わっているのかを議論し、そのディレクトリでgrunt watchを開始します。

私が必要な引数なしでスクリプトを呼び出すと、テーマをコマンドライン引数として指定する必要があるという警告が表示されています。

利用可能なオプションのリストを印刷したいと思います。これは私がこれまで持っているもので、テーマディレクトリ

...

THEME=$1 

if [ $THEME == '' ] 
then 
    echo 'Need to specify theme' 
else 
    cd 'workspace/aws/ghost/'$THEME'/' 
    grunt watch 
fi 

理想的には私はそう

THEME=$1 

if [ $THEME == '' ] 
then 
    echo 'Need to specify theme from the following' 
    ls workspace/aws/ghost 
else 
    cd 'workspace/aws/ghost/'$THEME'/' 
    grunt watch 
fi 
のようなテーマの親ディレクトリの lsechoラインの出力を交換したいです

しかし、これは私に次のエラーを与える。

./ghost_dev.sh: line 3: [: ==: unary operator expected 
+1

空の変数をチェックするには、 '-z' $ THEME"] 'を使用する必要があります。 – Kevin

+0

タイトルを編集しましたが[[-z "$ THEME"]] 'が完全に動作するなら' -z' – Luke

+0

'と試してみます - ありがとう。 – Luke

答えて

23

あなたはここに$THEME引用符で囲む必要があります。

if [ $THEME == '' ] 

そうでない場合、あなたは$THEMEが何に展開、テーマを指定しないと、シェルはこの構文エラーを見ているとき:

if [ == '' ] 

のような追加の引用符付きそう:

if [ "$THEME" == '' ] 

$THEMEの拡大ではなく、この有効な比較が得られます。

if [ "" == '' ] 

ランタイム構文エラーのため、この能力は、その背景より伝統的なプログラミング言語であるものに驚くべきことではなく、コマンドシェル(ボーンの伝統では、少なくともそれらの)多少異なるコードを解析することができます。多くの場合、シェルのパラメータは変数よりもマクロのように振る舞います。この動作は柔軟性を提供しますが、不注意なトラップも作成します。

あなたはこの質問にbashのをタグ付けするので、それは「新しい」テストはbashで利用可能な構文(およびkshの/ zshの)内部パラメータ展開、すなわち[[の結果に行わ一切単語分割がないことは注目に値します。 .. ]]。だから、あなたもこれを行うことができます:あなたは、引用符なしで逃げることができ

if [[ $THEME == '' ]] 

場所はhereに記載されています。しかし、あなたは明示的に単語分割が必要な場合を除いて(そして、配列があなたの問題を代わりに解決するかどうかを調べる場合を除いて)、常にパラメータ展開を引用するのは良い習慣です。

代わりに空の文字列と平等の-zテスト演算子を使用することがより慣用のようになります。

if [ -z "$THEME" ] 

あなたが技術的にこの単純なケースでは引用符は必要ありません。 [ -z ]はtrueと評価されます。しかし、より複雑な表現をしている場合、パーサーは混乱するので、引用符を使用するほうがよいでしょう。もちろん、[[ ... ]]はどちらか、ここに引用符を必要としない:

if [[ -z $THEME ]] 

しかし[[ ... ]]はPOSIX標準の一部ではありません。その件に関してはどちらも==ではありません。したがって、他のPOSIXシェルとの厳密な互換性を気にしている場合は、引用符で囲んで-zまたは=のいずれかを使用してください。

+0

OK、変数代入の前後に引用符を追加し、[[]]構文を使用し、ベストプラクティスのために "$ THEME"に引用符を追加しました。治療をしなさい!ありがとう。 – Luke

+3

割り当ては少し異なります。 RHSでは少なくとも単語の分割は起こらないので、私は忘れているコーナーケースに対して修正したいと思うが、 'THEME =" $ 1 "とTHEME = $ 1は同じだと思う。 – chepner

+0

@chepner - あなたが正しいです、割り当ての右側の展開に関する引用符は必要ありません。もちろん、リテラル空白を引用する必要があります。 –

0

二重引用符で構文を訂正してください。 $THEMEは、そうでない場合は、未定義または空の文字列と真である場合

if [ "$THEME" == "" ] then 
    echo 'Need to specify theme from the following' 
    ls workspace/aws/ghost 
2

[ "$THEME" ]はfalseに評価されます。 http://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html#Bash-Conditional-Expressionsを参照してください。声明は、この動作を利用し、さらに簡単な条件を持っている場合は、あなたを並べ替えることができます。

 
if [ "$THEME" ]; then 
    cd 'workspace/aws/ghost/'$THEME'/' 
    grunt watch 
else 
    echo 'Need to specify theme from the following' 
    ls workspace/aws/ghost 
fi 

"$THEME"は、その値が空白を含む場合には、二重引用符で囲む必要があります。

関連する問題