10

パターンが変数内に格納されているケースステートメントとパターンを一致させようとしています。最小限の例を次に示します。

PATTERN="foo|bar|baz|bla"

case "foo" in
    ${PATTERN})
        printf "matched\n"
        ;;
    *)
        printf "no match\n"
        ;;
esac

残念ながら「|」エスケープされているようです (興味深いことに、"*" または "?" はエスケープされていません)。これを機能させるには、つまり「foo」に一致させるにはどうすればよいですか? パターンは動的に構築されるため、変数に格納する必要があります。これは、POSIX 互換シェルで動作する必要があります。

4

7 に答える 7

3

これは機能するはずです:

PATTERN="foo|bar|baz|bla"

shopt -s extglob

case "foo" in
    @($(echo $PATTERN)))
        printf "matched\n"
        ;;
    *)
        printf "no match\n"
        ;;
esac
于 2009-10-13T19:14:29.887 に答える
1

あなたのパターンは実際にはパターンのリストであり、区切り文字|は文字通り指定する必要があります。あなたの唯一の選択肢はですeval。ただし、可能であればそれを避けるようにしてください。

于 2009-10-13T18:06:31.070 に答える
1

「ここから先には行けません」

私はパターン マッチングに case を使用するのが大好きですが、この状況では bourne shell の利点の限界を超えています。

この問題を解決するには 2 つのハックがあります。

フォークを犠牲にして、egrep を使用できます

pattern="this|that|those"

if
  echo "foo" | egrep "$pattern"  > /dev/null 2>&1
then
  echo "found"
else
  echo "not found"
fi

ループを使用して組み込みのみでこれを行うこともできます。状況によっては、これによりコードの実行が 10 億倍遅くなる可能性があるため、コードで何が起こっているかを必ず理解してください。

pattern="this|that|those"

IFS="|" temp_pattern="$pattern"
echo=echo

for value in $temp_pattern
do
  case foo 
  in
    "$list") echo "matched" ; echo=: ; break ;;
  esac
done
$echo not matched

これは明らかにホラー ショーであり、マップから少しでも何かを行おうとすると、シェル スクリプトがすぐに制御不能になる例です。

于 2009-11-06T17:37:57.803 に答える
0

Bashで正規表現マッチングを使用できます。

PATTERN="foo|bar|baz|bla"

if [[ "foo" =~ $PATTERN ]]
then
    printf "matched\n"
elif . . .
    . . .
elif . . .
    . . .
else
    printf "no match\n"
fi
于 2009-10-13T19:18:19.833 に答える
0

一部のバージョンexpr(GNU など) では、交互にパターン マッチングを行うことができます。

PATTERN="foo\|bar\|baz"
VALUE="bar"
expr "$VALUE" : "$PATTERN" && echo match || echo no match

それ以外の場合は、awk のようなツールを使用します。

awk -v value="foo" -v pattern="$PATTERN" '
    BEGIN {
        if (value ~ pattern) {
            exit 0
        } else {
            exit 1
        }
    }'

またはもっと簡潔に:

awk -v v="foo" -v p="$PATTERN" 'BEGIN {exit !(v~p)}'

次のように使用できます。

PATTERN="foo|bar|baz"
VALUE=oops
matches() { awk -v v="$1" -v p="$2" 'BEGIN {exit !(v~p)}'; }
if matches "$VALUE" "$PATTERN"; then
    echo match
else
    echo no match
fi
于 2009-10-13T18:52:05.253 に答える
-1

これにより、エスケープなどの必要がなくなります。

PATTERN="foo bar baz bla"

case "foo" in
    ${PATTERN// /|})
        printf "matched\n"
        ;;
    *)
        printf "no match\n"
        ;;
esac
于 2011-12-10T16:53:19.637 に答える