如何让.NET 7正则匹配结果按源文本顺序输出
解决正则匹配结果按源文本顺序输出的问题
问题场景
现有一段发票文本,通过多个正则模板提取服务行,但当前结果按模板执行顺序排列,与源文本中的实际顺序不符。需要调整代码,让提取结果与源文本里的出现顺序一致。
原代码及问题:
string text = @"Invoice 1234 Contract 45/5: Room Cleaning 100,00 Some other row Rental 200,00 Before VAT 300,00 VAT 30,00 Total 330,00 "; List<string> templates = new List<string>() { "Rental.*", ".*Cleaning.*$" }; List<string> results = new List<string>(); foreach (string template in templates) { var matches = Regex.Matches(text, template, RegexOptions.Multiline); for (int i = 0; i < matches.Count(); i++) results.Add(matches[i].Value); }
当前输出(按模板顺序):
Rental 200,00 Room Cleaning 100,00
期望输出(按源文本顺序):
Room Cleaning 100,00 Rental 200,00
解决方案
方法一:合并正则模板,单次匹配
将多个模板合并为一个正则表达式,用|分隔不同规则,这样一次调用Regex.Matches就能直接获取按源文本顺序排列的匹配结果。
修改后的代码:
string text = @"Invoice 1234 Contract 45/5: Room Cleaning 100,00 Some other row Rental 200,00 Before VAT 300,00 VAT 30,00 Total 330,00 "; // 合并模板为单个正则表达式 string combinedPattern = string.Join("|", new List<string>() { "Rental.*", ".*Cleaning.*$" }); List<string> results = Regex.Matches(text, combinedPattern, RegexOptions.Multiline) .Cast<Match>() .Select(m => m.Value) .ToList();
这种方法简单高效,适合模板数量不多、规则无冲突的场景。
方法二:收集匹配位置后排序
如果需要保留多模板的独立处理逻辑,可以先收集所有匹配项及其在源文本中的起始位置,再按位置排序。
Match对象自带Index属性,记录了匹配内容在原文本中的起始索引,利用这个属性就能实现排序。
修改后的代码:
string text = @"Invoice 1234 Contract 45/5: Room Cleaning 100,00 Some other row Rental 200,00 Before VAT 300,00 VAT 30,00 Total 330,00 "; List<string> templates = new List<string>() { "Rental.*", ".*Cleaning.*$" }; // 用元组存储匹配内容和起始位置 List<(string Value, int Position)> matchesWithPosition = new List<(string, int)>(); foreach (string template in templates) { var matches = Regex.Matches(text, template, RegexOptions.Multiline); foreach (Match match in matches) { matchesWithPosition.Add((match.Value, match.Index)); } } // 按位置排序后提取内容 List<string> results = matchesWithPosition.OrderBy(m => m.Position) .Select(m => m.Value) .ToList();
这种方法灵活性更高,即使模板需要单独处理(比如不同模板有不同的预处理逻辑),也能保证最终结果按源文本顺序排列。
内容的提问来源于stack exchange,提问作者Andrus
相关产品推荐
相关产品推荐

