文字列にA の前のどこかにパターンBが含まれている場合にのみ、パターンAをキャプチャする正規表現があります。
簡単にするために、Aは\b\d{3}\b
(つまり 3 桁の数字)、Bは単語「foo」であるとしましょう。
したがって、私が持っている正規表現は(?<=\b(?:foo)\b.*?)(?<A>\b\d{3}\b)
.
(?<= # look-behind
\b(?:foo)\b # pattern B
.*? # variable length
)
(?<A>\b\d{3}\b) # pattern A
たとえば、文字列の場合
"foo text 111, 222 and not bar something 333 but foo 444 and better 555"
それはキャプチャします
(111, 222, 333, 444, 555)
新しい要件があり、パターンCが先行するキャプチャを除外する必要があります。 Cが単語「バー」であるとしましょう。私が構築したいのは、表現する正規表現です
(?<= # look-behind
\b(?:foo)\b # pattern B
??????????? # anything that does not contains pattern C
)
(?<A>\b\d{3}\b) # pattern A
したがって、例の文字列では、キャプチャする必要があります
(111, 222, 444, 555)
もちろん、次のようなもの(?<=\b(?:foo)\b.*?)(?<!\b(?:bar)\b.*?)(?<A>\b\d{3}\b)
(?<= # look-behind
\b(?:foo)\b # pattern B
.*?
)
(?<! # negative look-behind
\b(?:bar)\b # pattern C
.*?
)
(?<A>\b\d{3}\b) # pattern A
「バー」の最初の出現後にすべてが除外され、キャプチャが行われるため、機能しません
(111, 222)
正規表現(?<=\b(?:foo)\b(?!.*?(?:\bbar\b)).*?)(?<A>\b\d{3}\b)
(?<= # look-behind
\b(?:foo)\b # pattern B
(?! # negative lookahead
.*? # variable lenght
(?:\bbar\b) # pattern C
)
.*? # variable lenght
)
(?<A>\b\d{3}\b) # pattern A
テスト文字列の最初の「foo」では、常に「bar」がサフィックスとして検出され、キャプチャのみが行われるため、機能しません
(444, 55)
これまでのところ、式の条件付きマッチングを使用し、(現在)後読みの内部で .net が右から左に一致してキャプチャすることを知っているため、次の正規表現を作成できました。(?<=(?(C)(?!)| (?:\bfoo\b))(?:(?<!\bbar)\s|(?<C>\bbar\s)|[^\s])*)(?<A>\b\d{3}\b)
(?<= # look-behind
(?(C) # if capture group C is not empty
(?!) # fail (pattern C was found)
| # else
(?:\bfoo\b) # pattern B
)
(?:
(?<!\bbar)\s # space not preceeded by pattern C (consume the space)
|
(?<C>\bbar\s) # pattern C followed by space (capture in capture group C)
|
[^\s] # anything but space (just consume)
)* # repeat as needed
)
(?<A>\b\d{3}\b) # pattern A
これは機能しますが、パターンA、B、およびCは、ここに投稿した例よりもはるかに複雑であるため、複雑すぎます。
この正規表現を単純化することは可能ですか? たぶん、バランシンググループを使用していますか?