关于后视支持
主要的正则表达式风格对不同的lookbehind 有不同的支持;有些施加了某些限制,有些甚至根本不支持。
- Javascript:不支持
- Python:仅固定长度
- Java:仅限有限长度
- .NET:没有限制
参考
Python
在 Python 中,仅支持固定长度的lookbehind,您的原始模式会引发错误,因为\d{1,2}
显然没有固定长度。您可以通过交替使用两个不同的固定长度后视来“解决”这个问题,例如:
(?<=^\d\/)\d{1,2}|(?<=^\d\d\/)\d{1,2}
或者,也许您可以将两个后视作为非捕获组的替代项:
(?:(?<=^\d\/)|(?<=^\d\d\/))\d{1,2}
(请注意,您可以\d
不使用括号直接使用)。
也就是说,使用捕获组可能要简单得多:
^\d{1,2}\/(\d{1,2})
请注意,findall
如果您只有一个组,则返回组 1 捕获的内容。捕获组比lookbehind 得到更广泛的支持,并且通常会导致更易读的模式(例如在这种情况下)。
此代码段说明了上述所有要点:
p = re.compile(r'(?:(?<=^\d\/)|(?<=^\d\d\/))\d{1,2}')
print(p.findall("12/34/56")) # "[34]"
print(p.findall("1/23/45")) # "[23]"
p = re.compile(r'^\d{1,2}\/(\d{1,2})')
print(p.findall("12/34/56")) # "[34]"
print(p.findall("1/23/45")) # "[23]"
p = re.compile(r'(?<=^\d{1,2}\/)\d{1,2}')
# raise error("look-behind requires fixed-width pattern")
参考
爪哇
Java 仅支持有限长度的lookbehind,因此您可以\d{1,2}
在原始模式中使用like。下面的代码片段证明了这一点:
String text =
"12/34/56 date\n" +
"1/23/45 another date\n";
Pattern p = Pattern.compile("(?m)(?<=^\\d{1,2}/)\\d{1,2}");
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group());
} // "34", "23"
请注意,这(?m)
是嵌入的Pattern.MULTILINE
,因此^
与每行的开头相匹配。另请注意,由于\
它是字符串文字的转义字符,因此您必须编写"\\"
以在 Java 中获得一个反斜杠。
C-夏普
C# 在lookbehind 上支持完整的正则表达式。以下代码段显示了如何在后视中使用+
重复:
var text = @"
1/23/45
12/34/56
123/45/67
1234/56/78
";
Regex r = new Regex(@"(?m)(?<=^\d+/)\d{1,2}");
foreach (Match m in r.Matches(text)) {
Console.WriteLine(m);
} // "23", "34", "45", "56"
请注意,与 Java 不同的是,在 C# 中,您可以使用@-quoted 字符串,这样您就不必转义\
。
为了完整起见,以下是在 C# 中使用捕获组选项的方法:
Regex r = new Regex(@"(?m)^\d+/(\d{1,2})");
foreach (Match m in r.Matches(text)) {
Console.WriteLine("Matched [" + m + "]; month = " + m.Groups[1]);
}
鉴于之前的text
,这将打印:
Matched [1/23]; month = 23
Matched [12/34]; month = 34
Matched [123/45]; month = 45
Matched [1234/56]; month = 56
相关问题