1

我正在尝试捕获两个字符串之间的匹配。

例如,我正在寻找出现在 Q 和 XYZ 之间的所有文本,使用“最快”匹配(不继续向外扩展)。这个字符串:

马戏团 Q 你好Q SOMETEXT XYZ今天是一天 XYZ 好的 XYZ

应该返回:

Q 某些文本 XYZ

但相反,它返回:

Q 你好 Q SOMETEXT XYZ

这是我正在使用的表达式: Q.*?XYZ

它向左走得太远了。当我在星号后使用问号时,它在骑行方面工作正常。我怎样才能对左侧做同样的事情,并在我击中第一个左 Q 后停止,使其与右侧的工作方式相同?我已经尝试过http://msdn.microsoft.com/en-us/library/az24scfc.aspx中的问号和其他符号,但有些东西我只是想不通。

我是一个正则表达式新手,所以对此的任何帮助将不胜感激!

4

2 回答 2

5

好吧,非贪婪匹配正在工作 - 它获得满足正则表达式的最短字符串。您必须记住的是,正则表达式是一个从左到右的过程。所以它匹配第一个 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))*?

根据您用于解析正则表达式的语言,它可能会尝试单独传回每个匹配的组(对于查找和替换很有用)。这使它无法这样做。

快乐的正则表达式!

于 2012-08-29T21:09:03.380 回答
3

贪婪的概念只适用于右侧。

要使表达式仅匹配 XYZ 之前的最后一个 Q,使其不匹配它们之间的 Q:

Q[^Q]*?XYZ
于 2012-08-29T21:08:23.103 回答