Grep 正規表現の結果が期待どおりではありませんか?

Grep 正規表現の結果が期待どおりではありませんか?

FreeBSD 11.1 を使用する場合:

#!/bin/sh

if printf 'abcde.fgh' | grep -iEq '^[^][$^*_-]'; then
    echo "test 1 success"
else
    echo "test 1 fail"
fi

echo

if printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'; then
    echo "test 2 success"
else
    echo "test 2 fail"
fi

出力:

test 1 success

grep: Unmatched [ or [^
test 2 fail

しかし、私の知る限り、これらは同じ結果になるはずです。どちらも、最初の文字 (のみ) に、指定された非アルファベット文字のリストに含まれないという条件が含まれています。正規表現の内訳:

  • ^= 文字列の始まり
  • [^...]= これらの文字のいずれも一致しない場合に一致
  • リスト内では、]が最初の文字である必要があり、^最初の文字であってはならず、 - が最後の文字である必要があります。 は][.^$_-リテラル文字の有効なリストであり、文字列はそれらのいずれとも一致してはなりません。
  • 混乱を避けるために、これはリスト内の][リテラル"]"と文字であることを意味することに注意してください。"["ない2 つのリストを閉じて再開します。

2つの式の唯一の違いは"."、リスト内にあるため、not literal .最初の文字がリテラルと一致しないことです。"."

何が足りないのでしょうか? おそらく、非常に明白で単純な何かでしょうか?

答え1

いくつかの他の構文規則が抜けています。括弧展開では、単純な範囲に加えて、 で始まる複数文字の式もいくつかあります[。(正規表現(7)マニュアルリナックスまたはフリーBSD「これらを除いて'[' を使ったいくつかの組み合わせ(次の段落を参照してください)。これらは次のとおりです。

  • 照合要素: [..]
  • 同値クラス: [==]
  • キャラクタークラス: [::]

(次のような表現を見たり使ったりしたことがあるかもしれません。これらは実際には括弧展開の唯一の要素である[[:digit:]]文字クラスです。)[:digit:][…]

したがって、あなたの場合、.は の直後にあるため[、照合要素の開始区切り文字として認識されます。GNU grep 3.1 には正しいエラー メッセージがあります。

$ printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'
grep: Unmatched [, [^, [:, [., or [=

同じ表現を使用して、[...]たとえばまたは を使用して[=.=]通常のドットを含めたり、[=-=]移動する場所がない場合は同様にダッシュを一致させたりすることで、このような状況から脱出することができます。

関連情報