【发布时间】:2017-09-14 08:22:36
【问题描述】:
我正在尝试制作一个正则表达式以从 10 位数字中获取所有可能的连续 4 位数字。喜欢
num = "2345678901";
输出:
2345、3456、4567、5678、6789、7890、8901
这些简单的正则表达式不起作用:
[\d]{4}
(\d\d\d\d)
【问题讨论】:
我正在尝试制作一个正则表达式以从 10 位数字中获取所有可能的连续 4 位数字。喜欢
num = "2345678901";
输出:
2345、3456、4567、5678、6789、7890、8901
这些简单的正则表达式不起作用:
[\d]{4}
(\d\d\d\d)
【问题讨论】:
您需要使用(?=(\d{4})) 正则表达式来匹配重叠的匹配项。
您使用的正则表达式都在消耗 4 位文本块,因此重叠值不匹配。使用(?=...) 正向前瞻,您可以测试输入字符串中的每个 位置,并从这些位置捕获 4 位块,而无需消耗字符(即不将正则表达式引擎指针移动到这 4 位数字块之后的位置)。
var data = "2345678901";
var res = Regex.Matches(data, @"(?=(\d{4}))")
.Cast<Match>()
.Select(p => p.Groups[1].Value)
.ToList();
Console.WriteLine(string.Join("\n", res));
【讨论】:
(?=...) 是一个积极的前瞻,一个零宽度的断言,一个让我们检查(或强制)某些字符存在的构造 after字符串中的当前位置。 Bikonja:我将我的结果与预期的结果进行了比较,它们是相同的。
(?=(\d{4})) 并替换为 \nOVERLAPPED: $1\n。然后,用^OVERLAPPED:\h*\d{4}$ 正则表达式为重叠的行添加书签,将所有添加书签的行复制到一个新文件并删除“OVERLAPPED:”。这不是直截了当的,但有可能。
您绝对需要使用正则表达式吗?使用简单的循环可以更快地完成相同的操作。
private IEnumerable<string> getnums(string num)
{
for (int i = 0; i < num.Length - 3; i++)
{
yield return num.Substring(i, 4);
}
}
private IEnumerable<string> DoIt(string num)
{
var res = Regex.Matches(num, @"(?=(\d{4}))")
.Cast<Match>()
.Select(p => p.Groups[1].Value)
.ToList();
return (IEnumerable<string>)res;
}
平均而言,简单循环大约需要 RegEx 版本的一半时间。
static void Main(string[] args)
{
var num = "2345678901";
Stopwatch timer = new Stopwatch();
timer.Start();
foreach (var number in getnums(num))
{
// Yum yum numbers
}
timer.Stop();
Console.WriteLine(timer.Elapsed.Ticks);
timer.Reset();
timer.Start();
foreach (var number in DoIt(num))
{
// Yum yum numbers
}
timer.Stop();
Console.WriteLine(timer.Elapsed.Ticks);
}
【讨论】: