我在C#程序中有以下正则表达式,并且很难理解它:
(?<=#)[^#]+(?=#)
我会将其分解为我认为理解的内容:
(?<=#) a group, matching a hash. what's `?<=`?
[^#]+ one or more non-hashes (used to achieve non-greediness)
(?=#) another group, matching a hash. what's the `?=`?
所以我遇到的问题是?<=
和?<
部分。从阅读MSDN开始,?<name>
用于命名组,但在这种情况下,尖括号永远不会关闭。
我在文档中找不到?=
,搜索它真的很难,因为搜索引擎大多会忽略那些特殊的字符。
答案 0 :(得分:33)
他们被称为外观;它们允许您断言模式是否匹配,而不实际进行匹配。有4种基本的外观:
pattern
...
(?=pattern)
- ...到当前位置的右(看提前)(?<=pattern)
- ...到当前位置的左(看在后面)pattern
不匹配
(?!pattern)
- ... right (?<!pattern)
- ...到 left 简单提醒一下:
=
肯定,!
否定 <
看起来在后面,否则看起来提前 有人可能会争辩说上面的模式中的外观不是必需的,#([^#]+)#
可以很好地完成工作(提取\1
捕获的字符串以获取非#
)。
不完全。区别在于,由于环视不会匹配 #
,因此可以在下次尝试查找匹配时再次“使用”它。简单来说,lookarounds允许“匹配”重叠。
考虑以下输入字符串:
and #one# and #two# and #three#four#
现在,#([a-z]+)#
将提供以下匹配项(as seen on rubular.com):
and #one# and #two# and #three#four#
\___/ \___/ \_____/
将此与(?<=#)[a-z]+(?=#)
进行比较,匹配:
and #one# and #two# and #three#four#
\_/ \_/ \___/ \__/
不幸的是,这不能在rubular.com上展示,因为它不支持lookbehind。但是,它确实支持前瞻,因此我们可以使用匹配(as seen on rubular.com)的#([a-z]+)(?=#)
执行类似操作:
and #one# and #two# and #three#four#
\__/ \__/ \____/\___/
答案 1 :(得分:4)
正如另一张海报所提到的,这些是 lookarounds ,这是用于更改匹配内容以及何时更改内容的特殊构造。这说:
(?<=#) match but don't capture, the string `#`
when followed by the next expression
[^#]+ one or more characters that are not `#`, and
(?=#) match but don't capture, the string `#`
when preceded by the last expression
因此,这将匹配两个#
之间的所有字符。
在许多情况下,前瞻和外观非常有用。例如,请考虑“匹配所有b
未遵循a
”的规则。您的第一次尝试可能类似于b[^a]
,但这不对:这也会与bu
中的bus
或bo
中的boy
相匹配,但是您只想要b
。它与b
中的cab
不匹配,即使后面没有a
,因为没有其他字符可供匹配。
要做到这一点,你需要一个前瞻:b(?!a)
。这表示“匹配b
但之后与a
不匹配,并且不会使匹配成为该部分”。因此它只匹配b
中的bolo
,这就是你想要的;同样,它会匹配b
中的cab
。
答案 2 :(得分:1)
他们被称为 look-arounds :http://www.regular-expressions.info/lookaround.html