我正在尝试捕获两个字符串之间的匹配。
例如,我正在寻找Q和XYZ之间出现的所有文本,使用“最快”匹配(不继续向外扩展)。这个字符串:
马戏团Q你好那里 Q SOMETEXT XYZ 今天是XYZ好的XYZ
应该返回:
Q SOMETEXT XYZ
但相反,它会返回:
问你好Q SOMETEXT XYZ
这是我正在使用的表达式: 问。*?XYZ
它向左走得太远了。当我在星号后使用问号时,它在骑行方面工作正常。我怎么能在左侧做同样的事情,并在我第一次离开Q后停下来,让它与右侧的工作方式相同?我已经尝试了来自http://msdn.microsoft.com/en-us/library/az24scfc.aspx的问号和其他符号,但有些东西我只是想不出来。
我是一名正则表达式的新手,所以对此有任何帮助都会受到赞赏!
答案 0 :(得分:4)
嗯,非贪婪的匹配正在运行 - 它获得满足正则表达式的最短字符串。你必须要记住的是正则表达式是一个从左到右的过程。所以它匹配第一个Q,然后获得最短的字符数,然后是XYZ。如果你不希望它超过任何Q,你必须使用否定的字符类:
Q[^Q]*?XYZ
[^ Q]匹配任何一个不是Q的字符。请注意,这只适用于单个字符。如果您的开场分隔符是多个字符,则必须以不同的方式执行。为什么?好吧,取分隔符'PQR',字符串是
foo PQR bar XYZ
如果您尝试使用之前的正则表达式,但是您将字符类扩展为:
PQR[^PQR]*?XYZ
然后你会得到
'PQR bar XYZ'
如你所料。但是如果你的字符串是
foo PQR Party Time! XYZ
你不会得到任何比赛。这是因为[]描绘了一个“字符类” - 它恰好与一个字符匹配。使用这些类,您可以匹配一系列字符,只需列出它们即可。
th[ae]n
将匹配'than'和'then',但不是'thin'。在开头放置一个克拉('^')否定了该类 - 意思是“匹配除了这些字符之外的任何东西” - 所以通过将我们的单字符分隔符转换为[^ PQR],而不是说“不是'PQR'”,你'说“不'P','Q'或'R'”。如果需要,您仍然可以使用此功能,但前提是您100%确定分隔符中的字符仅在您的分隔符中。如果是这种情况,使用贪婪匹配更快,并且只取消分隔符的第一个字符。正则表达式是:
PQR[^P]*XYZ
但是,如果你不能保证,那么匹配:
PQR(?:.(?!PQR))*?XYZ
正则表达式并不直接支持负字符串匹配(因为当您考虑它时,无法定义),因此您必须使用否定前瞻。
(?!PQR)
就是这样一个先行者。这意味着“断言接下来的几个字符不是这个内部正则表达式”,而不匹配任何字符,所以
.(?!PQR)
匹配任何未跟随PQR的字符。将其包裹在一个组中,以便您可以懒惰地重复它,
(.(?!PQR))*?
并且您匹配“不包含我的分隔符的字符串”。我唯一做的就是添加一个?:来使它成为一个非捕获组。
(?:.(?!PQR))*?
根据您用来解析正则表达式的语言,它可能会尝试单独传回每个匹配的组(对查找和替换很有用)。这使它无法做到这一点。
快乐的复兴!
答案 1 :(得分:3)
贪婪的概念只适用于右侧。
要使表达式仅匹配XYZ之前的最后一个Q,请使它们与它们之间的Q不匹配:
Q[^Q]*?XYZ