私は次の正規表現を持っています:a?\W*?b
そして私は文字列を持っています,.! ,b
一致を検索すると が得られますが、期待どおり,.! ,b
ではありませんb
。何故ですか?必要なものを取得するために正規表現を変更する方法は?
ご協力ありがとうございました。
7 に答える
怠惰な量指定子は、ここではあなたが望むものには役に立ちません。何が起こっているのか見てみましょう。
正規表現エンジンは文字列の先頭から開始します。最初に との一致を試みa
ます。a
できませんが、オプションなので問題ありません。
次に、遅延がある\W*?
ため、正規表現エンジンはそれをスキップしますが、現在の位置は記憶しています。
次に、一致を試みb
ます。できないので、バックトラックして,
with との一致に成功し\W*?
ます。次に、一致の試行を続けますb
(遅延量指定子のため)。それはまだできず、再びバックトラックします。最終的に正規表現エンジンが に到達するまで、これが数回繰り返されますb
。これで一致が完了しました。正規表現エンジンが成功を宣言します。
したがって、正規表現は指定どおりに機能します-意図したとおりではありません。質問は次のとおりです。正規表現に正確に何をさせたいのですか?
たとえば、本当に必要なものが次の場合:
と単語以外の文字がb
前にある場合を除き、単独で一致し、その場合は からまでのすべてに一致し、a
a
b
b|a\W*b
遅延式は右側からのみ遅延します。つまり、右側の文字を削除してできるだけ短くしますが、左側の文字は削除しません。
後でマッチを開始するには、その前に、マッチさせたくない文字を飲み込む貪欲な表現が必要です。
または、Tim が示したように、最初の文字と、最初の文字が存在する場合は次の区切り文字のみを一致させることで、一致を後で開始することができます。
たとえば、次のようにするとうまくいきます。(a\W*)?b
問題を解決する方法をよりよく知るには、より多くの例を含める必要があります。
正規表現は、次のように文字列全体と一致します。
- a、0 回または 1 回の繰り返し (この場合は "")
- 英数字以外の任意の文字、任意の回数の繰り返し、可能な限り少ない (",.! ," この場合)
- b
あなたの場合、正規表現は文字列全体に一致するため、 b だけは見つかりません(同じ部分の複数の一致は見つかりません)。
「,.!」のような文字列で検索すると、,db' b が見つかります。
a?
は、「のゼロまたは1つのインスタンスが必要です」a
と述べています-インスタンスがゼロであるため、これは満足され、その後に
\W*
「単語以外の文字が 0 個以上欲しい」と言い、これは句読点とスペース文字で満たされ、最後に
b
「文字に一致」b
と言いますが、それは実行します。したがって、文字列全体が正規表現を満たします。
誰かが可能な解決策を提案する前に、可能な入力の例をもっと挙げると役に立ちます。
あなたの例は、が正規表現の一部である理由を示していませんが、このような後読みを使用できるように見える文字列でa?
のみ一致します。b
,.! ,b
(?=\W*?)b
これb
は、「単語以外の文字」である文字が前にある文字に 0 回および無制限に (できるだけ少ない回数) 一致します。
a
たとえばandb
のような文字列でのみ一致させたい場合はa,.! ,b
、キャプチャ グループを使用する必要があります。(a?)\W*?(b)
ここで、グループ 1 はa
存在する場合とグループ 2を保持しますb
正規表現を貪欲または非貪欲であると言うのは間違いです。正規表現全体で貪欲でない量指定子を使用できますが、発見したように、最も早い機会に一致を開始しようとします。同様に、貪欲な量指定子のみを使用する正規表現は、可能な限り最長の一致を返すことが保証されていません。例えば、
Regex.Match("foo bar", @"\w+ (?:b|bar)")
... が返されます。これはfoo b
、後の代替がより長い一致をもたらす場合でも、代替は機能する最初の代替に落ち着くためです。(私が .NET のような Perl 由来の正規表現フレーバーについて話していることに注意してください。 や のようないくつかのフレーバーは、awk
実際egrep
に可能な限り長い一致を保持します。しかし、それらのフレーバーには貪欲でない量指定子がないため、貪欲ではありません。単なるデフォルト モードではありません。これが唯一のモードです。)
要するに、貪欲または非貪欲な正規表現などはなく、貪欲または非貪欲な量指定子のみがあります。