在令人敬畏的正则表达式模块(https://pypi.python.org/pypi/regex(的pypi页面中,指出\G可以"在负可变长度回溯中使用,以限制回溯的距离"。非常有趣,但是该页面没有给出任何示例,当我试图想象一个时,我的白带正则表达式只是窒息。
谁能描述一些示例用例?
下面是一个创造性地使用G
和负面回溯的示例:
regex.match(r'bw+b(?:s(w+b)(?<!G.*b1b.*b1b))*', words)
words
应该是由单个空格分隔的字母数字字符字符串,例如 "a b c d e a b b c d"
。
该模式将匹配一系列唯一单词。
-
w+
- 匹配第一个单词。 -
(?:s(w+b) )*
- 匹配其他单词... -
(?<!G.*b1b.*b1b)
- ...但是对于添加的每个新单词,请检查它是否尚未出现,直到我们到达G
。
模式末尾的回溯(限制在 G
(可以断言当前匹配的另一个条件,否则这是不可能的。基本上,该模式是在正则表达式中使用 AND 逻辑的前瞻的变体,但不限于整个字符串。
下面是 .Net 中的一个工作示例,它共享相同的功能。
在 Python 2 中使用 findall
和 regex
模块尝试相同的模式会给我一个分段错误,但match
似乎有效。
我能想到的一个例子是在正面回望中使用G
来用逗号分隔CSV行:
regex.split(r'(?<=G(?:"[^"]*(?:""[^"]*)*"|[^"]*)),', csv)
这是您只能通过可变长度后视和G
来执行的变体。
通常,如果要使用split
请添加直到行尾的预视,并检查以下记录是否全部有效,如图,(?=([^"]*"[^"]*")*[^"]*$)
。这有点烦人,因为您一遍又一遍地匹配字符串上的结尾。
我们也从未明确提到不带引号的值不是逗号([^,]
(,因为我们使用自上一个逗号以来G
来匹配。
这是一个可能比创意更有用的示例。
它使用从上一场比赛(G
(开始的可变长度负回溯向前检查到当前位置。
在这种情况下(?<!Ga+)b
,结果是它匹配字符串中所有其他b
,其中 b 由一个或多个 a
分隔。
这也可以在固定宽度的后视中完成,例如(?<!Ga)b
,结果是它匹配字符串中的所有其他b
,其中 b 由一个a
分隔。
这是一种模板,其中a
和b
可以是更大的表达式,并且具有更多
内容意义。
(需要注意的一件事是,在负面回溯中使用G
时,
很容易满足否定断言。所以,这种事情gotcha
写满了!!
没有 Python(最新的,测试版?(来测试它,所以下面使用 C# 控制台应用程序。
string strSrc = "abaabaabaabaabaab";
Regex rxGtest = new Regex(@"(?<!Ga+)b");
Match _m = rxGtest.Match(strSrc);
while (_m.Success)
{
Console.WriteLine("Found: {0} at position {1}", _m.Groups[0].Value, _m.Index);
_m = _m.NextMatch();
}
输出:
Found: b at position 4
Found: b at position 10
Found: b at position 16