2017-01-04 18 views
0

私のBash-Scriptは、変数の先頭に応じて、何か別のことを行わなければなりません。 私は次のスクリプトを実行すると:Linux bash if - elifが期待どおりに動作しない

#!/bin/bash 

line="__B something" 

if [ -n $(echo "$line" | grep "^__A") ]; then 
    echo "Line __A" 
elif [ -n $(echo "$line" | grep "^__B") ]; then 
    echo "Line __B" 
elif [ -n $(echo "$line" | grep "^__C") ]; then 
    echo "Line __C" 
elif [ -n $(echo "$line" | grep "^__D") ]; then 
    echo "Line __D" 
elif [ -n $(echo "$line" | grep "^__E") ]; then 
    echo "Line __E" 
elif [ $(echo "$line" | grep "^__F") ]; then 
    echo -n "Line __F" 
else 
    echo "something other" 
fi 

バッシュは__B:

出力付き文字列の先頭のであることを認識しません:

Line __A 

私のスクリプトの何が問題なのですが? ありがとうございます!

+1

あなたが最後に置き忘れように、それは '見えます-n' – Matthias

+3

もっと引用符を使う! 'if [-n" $(echo ...) "];それから。パラメータの拡張を引用してください! (しかしあなたのデザインはとにかくかなり悪いです)。 –

+0

@gniourf_gniourf:あなたが表示するスナップだけでなく、* whole * 'echo | grep'コマンドを二重引用しようとすると、' $ line'の埋め込みスペースを考えると、それほど単純ではないことがわかります。 – cdarke

答えて

1

私は、条件付きの場合、[[[をbashで使用するという違いの微妙さに関係していると考えています。

[[]]のいずれかを使用できます(動作しているようです)。

if [[ -n $(echo "$line" | grep "^__A") ]]; then 
    echo "Line __A" 

か、この

if [ -n "$(echo '$line' | grep '^__A')" ]; then 
    echo "Line __A" 

[[のようなサブシェルが少ない驚きを持っており、一般的に使用する方が安全です引用することができます。しかし、 ポータブルではありません - Posixは何を行い、いくつかのシェルだけを指定していません (bashの横に、私もkshがサポートしていると聞きました)。たとえば、 あなたは、ファイルが存在するかどうかをテストするために

[[ -e $b ]]

を行うことができます。しかし、[では、引数を分割して"a*"[[ という文字通り)というように展開するので、$b、 を引用する必要があります。これはまた、 のプログラムと同じように、普通は のプログラムと同じように、外部の プログラムと同じように、その引数を受け取ります(ただし、組み込みの場合もありますが、それでもまだこの特別な処理は ではありません)。

this答えがここにあります。あなたのケースでは、おそらくbashはスペース上のあなたの文字列を分離しており、それはいくつかの副作用を持っています。

2

あなたは何が起こっている見ることができるよりもxtraceオプションを使用してスクリプトを実行した場合:あなたが使用しているため、古いtestビルトイン(そうでない場合は[として知られている)拡張が行われているが、

bash -x your-script 
+ line='__B something' 
++ echo '__B something' 
++ grep '^__A' 
+ '[' -n ']' 
+ echo 'Line __A' 
Line __A 

-nを除き、テストすることはありません。正しく物事を引用します[[キーワードを使用する:

bash -x your-script 
+ line='__B something' 
++ echo '__B something' 
++ grep '^__A' 
+ [[ -n '' ]] 
++ echo '__B something' 
++ grep '^__B' 
+ [[ -n __B something ]] 
+ echo 'Line __B' 
Line __B 

をただし、外部プログラムgrepを使用することは無駄です。bashの最近のバージョンでは、正規表現(RES)ビルトイン(結合演算子=~を使用して)を持っていますが、この場合のREを必要としない、簡単なグロブが行います。

#!/bin/bash 

line="__B something" 

if [[ $line == __A* ]]; then 
    echo "Line __A" 
elif [[ $line == __B* ]]; then 
    echo "Line __B" 
elif [[ $line == __C* ]]; then 
    echo "Line __C" 
elif [[ $line == __D* ]]; then 
    echo "Line __D" 
elif [[ $line == __E* ]]; then 
    echo "Line __E" 
elif [[ $line == __F* ]]; then 
    echo -n "Line __F" 
else 
    echo "something other" 
fi 
関連する問題