我有一个正则表达式,我在 http://gskinner.com/RegExr/ 上进行了测试,它有效,但当我在我的C#应用程序中使用它时失败了。
我的正则表达式:(?<!\d)\d{6}\K\d+(?=\d{4}(?!\d))
文本:4000751111115425
结果:111111
我的正则表达式哪里出了问题?
我的正则表达式:(?<!\d)\d{6}\K\d+(?=\d{4}(?!\d))
文本:4000751111115425
结果:111111
我的正则表达式哪里出了问题?
您遇到的问题是,.NET正则表达式不支持\K
,即“放弃已匹配的内容”。
我认为您的正则表达式的含义是“匹配超过十个\d
数字的任何字符串,并尽可能多地匹配数字,然后丢弃前6个数字和最后4个数字”。
我认为符合.NET标准的正则表达式是:
(?<=\d{6})\d+(?=\d{4})
实现相同的效果。请注意,对于没有更多\d
的负向先行/后行并不是必需的,因为\d+
是贪婪的——引擎已经会尝试匹配尽可能多的数字。
\s\S*(?:<p class="text_obisnuit">|\G)(?:(?!</p>).)*?\s\K\s+|(?<=<p class="text_obisnuit">)\s+|\s+(?=</p>)
,那么 \K 的替代方案是什么? - Just Me\K
前面的部分放到正向先行断言里,就像第二个备选方案已经使用的那样 ((?<= ... )
)。 - Rawling\K
操作符(用于从匹配内存缓冲区中丢弃到目前为止所有已匹配的文本)可以通过两种技术来模拟:
例如,
a+b+c+=\K\d+
(demo) = .NET (?<=a+b+c+=)\d+
或 a+b+c+=(\d+)
(并捕获第 1 组的值)^[^][]+\K.*
(demo) = .NET (?<=^[^][]+)(?:\[.*)?$
(demo) 或(更好的写法)^[^][]+(.*)
(demo)。[^][]+
可以匹配与.*
相同的文本(这些模式重叠),并且由于两个模式之间没有明确的边界,仅使用回顾后查找实际上不起作用,需要额外的技巧才能使其工作。
捕获组方法是通用的,在所有情况下都应该有效。
由于\K
使正则表达式引擎“忘记”到目前为止消耗的匹配部分,因此在此处最好的方法是使用捕获组来获取左侧上下文后需要获取的匹配部分:
using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
var text = "Text 4000751111115425";
var result = Regex.Match(text, @"(?<!\d)\d{6}(\d+)(?=\d{4}(?!\d))")?.Groups[1].Value;
Console.WriteLine($"Result: '{result}'");
}
}
(?<!\d)
- 左手数字边界\d{6}
- 六个数字(\d+)
- 捕获组1:一个或多个数字(?=\d{4}(?!\d))
- 正向先行断言,匹配紧随其后的位置,紧跟着四个数字,不再紧跟着另一个数字。
\K
。我认为最接近的替代方法是使用(?<!\d)\d{6}(\d+)(?=\d{4}(?!\d))
,然后查看match.Groups[1].Value
而不是match.Value
。(注:如果没有♦一次性关闭此问题,这将是一个答案。) - Rawling(?<=\d{6})\d+(?=\d{4})
同样可以工作,因为+
是贪婪的。 - Rawling