我有一个正则表达式,仅当字符串在 A 之前的某处包含模式B时才捕获模式A。
假设,为了简单起见,A是\b\d{3}\b
(即三个数字),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是单词“bar”。我想要构建的是一个表达的正则表达式
(?<= # 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
将不起作用,因为它会在“bar”第一次出现后排除所有内容,并且捕获将是
(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比我在此处发布的示例复杂得多。
是否可以简化此正则表达式?也许使用平衡组?