bash / bourneに「in」演算子はありますか?


17

私は次のような機能を果たす「in」演算子を探しています。

if [ "$1" in ("cat","dog","mouse") ]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

これは、たとえば、複数の「または」テストを使用する場合と比較して、明らかに短い文です。

回答:


31

使用できますcase...esac

$ cat in.sh 
#!/bin/bash

case "$1" in 
  "cat"|"dog"|"mouse")
    echo "dollar 1 is either a cat or a dog or a mouse"
  ;;
  *)
    echo "none of the above"
  ;;
esac

$ ./in.sh dog
dollar 1 is either a cat or a dog or a mouse
$ ./in.sh hamster
none of the above

kshbash -O extglobまたはzsh -o kshglob、あなたはまた、拡張されたグロブパターンを使用することができます。

if [[ "$1" = @(cat|dog|mouse) ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

bashksh93またはzsh、あなたはまた、正規表現比較を使用することができます。

if [[ "$1" =~ ^(cat|dog|mouse)$ ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

二重括弧の理由は何ですか?再度、感謝します!
-mrjayviper

1
@mrjayviperダブルブラケットは拡張テストコンストラクト-正規表現演算子=~はPOSIXシングルブラケットテスト内では無効です
-steeldriver

1
@steeldriverのみ[POSIXですが、[[bashの、kshの(どうやらそれはそこに由来しています、とのzshの拡張機能である。 case例は、ほとんどすべてのPOSIX、けれどもある
Sergiy Kolodyazhnyy

2
@StéphaneChazelas少なくともbash 4.1-alpha以降では、extglogを明示的に設定する必要はありません。bashの変更からs。互換性のため、= [および!=演算子のパターン引数を[[コマンドに解析するときは、一時的にextglobを強制的にオンにします。
アイザック

@steeldriver $ 1をcase "$1" in引用符で囲む必要はありません。そのトークンでは単語の分割やパス名の展開は行われません。
アイザック

9

bashには「in」テストはありませんが、正規表現テスト(bourneにはありません)はあります。

if [[ $1 =~ ^(cat|dog|mouse)$ ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

通常、変数を使用して記述されます(引用の問題は少なくなります)。

regex='^(cat|dog|mouse)$'

if [[ $1 =~ $regex ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

古いBourneシェルの場合、大文字と小文字の一致を使用する必要があります。

case $1 in
    cat|dog|mouse)   echo "dollar 1 is either a cat or a dog or a mouse";;
esac

これは私に受け入れられた答えです。
ナムG VU

6

case一致させたいペットの固定セットがある場合、aの使用は問題ありません。しかし、実行時にパターンを構築する必要がある場合caseは機能しません。拡張されたパラメーター内からの代替を解釈しないためです。

これはリテラル文字列のみに一致しますcat|dog|mouse

patt='cat|dog|mouse'
case $1 in 
        $patt) echo "$1 matches the case" ;; 
esac

ただし、正規表現が一致する変数を使用できます。変数が引用されていない限り、変数内の正規表現演算子には特別な意味があります。

patt='cat|dog|mouse'
if [[ "$1" =~ ^($patt)$ ]]; then
        echo "$1 matches the pattern"
fi

連想配列を使用することもできます。キーが存在するかどうかを確認することは、inBashが提供する演算子に最も近いものです。構文は少しいですが:

declare -A arr
arr[cat]=1
arr[dog]=1
arr[mouse]=1

if [ "${arr[$1]+x}" ]; then
        echo "$1 is in the array"
fi

設定され${arr[$1]+x}ているx場合arr[$1]は展開され、設定されていない場合は空になります。


5

テストでステートメントを使用することもできますが、コードは少し複雑に見えます。caseif

if case "$1" in (cat|dog|mouse) true ;; (*) false; esac; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

またはわずかに短く、

if ! case "$1" in (cat|dog|mouse) false; esac; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

これは、case句のパターンマッチングを行うためだけに句を使用していifます。不要なtrue / falseテストが導入されます。

単に使用する方が良いですcase

case "$1" in
    cat|dog|mouse)
        printf '"%s" is one of cat, dog or mouse\n' "$1"
        ;;
    *)
        printf '"%s" is unknown\n' "$1"
esac

これをしないでください:

is_one_of () {
    eval "case $1 in ($2) return 0; esac"
    return 1
}

if is_one_of "$1" 'cat|dog|mouse'; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

またはこれ:

is_one_of () (
    word=$1
    shift
    IFS='|'
    eval "case $word in ($*) return 0; esac"
    return 1
)

if is_one_of "$1" cat dog mouse; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

...単にif完全に合理的なcaseステートメントの代わりにコードでステートメントを使用できるようにするために、より危険な問題を追加しているだけだからです。


ケースを関数呼び出しに分割し、ifステートメント内で終了ステータスを評価する方が良いでしょうか?
セルギーKolodyazhnyy

@SergiyKolodyazhnyyそして、パターンを関数の引数にしますか?それは何をする必要がありますevalcase、その場合には文を、それがさらに発生しやすいエラーになります。
クサラナナンダ

この場合、単純なパターンがあり、それぞれを位置パラメーターとしてfunctionおよびdoに渡すことができます"$1"|"$2"|"$3"。また、unix.stackexchange.com / a / 234415/85039 しかし、ええ、それは少し毛深いです。
セルギーKolodyazhnyy

4

grep アプローチ。

if echo $1 | grep -qE "^(cat|dog|mouse)$"; then 
    echo "dollar 1 is either a cat or a dog or a mouse"
fi
  • -q画面への出力を回避するために(より入力するのが速い>/dev/null)。
  • -E拡張正規表現の(cat|dog|mouse)側面ではこれが必要です。
  • ^(cat|dog|mouse)$(起動任意の行と一致する^(ネコ、イヌ又はマウスで)を(cat|dog|mouse)行(の終わりが続きます)$
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.