1. ホーム
  2. バッシュ

[解決済み】シェルのif文で複数の条件を表現するには?

2022-03-25 22:17:51

質問

複数の条件をこのように表現したい。

if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]   
then  
    echo abc;  
else  
    echo efg;   
fi  

と表示されますが、スクリプトを実行すると

syntax error at line 15: `[' unexpected,

ここで、15行目がif ...を示すものです。

この条件では何が問題なのでしょうか?やはり () .

解決方法は?

古典的な手法(メタ文字のエスケープ)。

if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi

への参照を囲みました。 $g 二重引用符で囲むのは、一般的に良い習慣です。 厳密には、括弧は必要ありません。 -a-o を使うと、それらがなくても正しくなります。

なお -a-o 演算子は、POSIX仕様に含まれる test は、別名 [ の一部であったため)、主に後方互換性のためです。 test は、例えば第7版UNIXのように)しかし、POSIXでは「時代遅れ」として明示的にマークされています。 Bash ( 条件式 の古典的な意味とPOSIXの意味を先取りしているようです。 -a-o と、引数を取る独自の代替演算子で構成されています。


少し注意すれば、より現代的な [[ 演算子がありますが、BashとKorn Shell(例)のバージョンが同じである必要はないので注意してください。

for g in 1 2 3
do
    for c in 123 456 789
    do
        if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
        then echo "g = $g; c = $c; true"
        else echo "g = $g; c = $c; false"
        fi
    done
done

Mac OS X の Bash 3.2.57 を使用した実行例です。

g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false

の変数を引用する必要はありません。 [[ と同じように [ と同じように独立したコマンドではないためです。 [ があります。


古典的な質問ではありませんか?

私もそう思っていました。 しかし、別の選択肢もある、すなわち

if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi

確かに、「ポータブルシェル」のガイドラインを読むと autoconf ツールや関連パッケージでは、この表記法 - ' || と' && というのが彼らの推奨するところです。 というところまで行けると思います。

if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi

アクションがechoのような些細なものである場合、これは悪くないと思います。 繰り返されるアクションブロックが複数行に及ぶ場合は、繰り返しが苦痛になるので、以前のバージョンのいずれかが望ましいです - あるいは、アクションを関数にラップして、別の then ブロックを作成します。