C#中如何通过正则表达式一次性提取多个键值对捕获结果
问题原因
你当前使用的正则用|做分支交替,规则是每匹配到任意一个分支的行,就会生成一个独立的Match对象,这是Regex.Matches返回5个分散结果的核心原因。如果直接调用Match方法只返回第一个命中的分支,剩余分组自然没有捕获值。
有两种成熟的实现方式可以拿到所有目标字段:
方案1:调整正则实现单次全量匹配
修改正则规则,允许目标字段之间穿插其他无关行,仅调用一次Match方法就能拿到所有命名分组的捕获值,正则和调用代码如下:
var matchResult = Regex.Match( pageText, @"^Ort Lieferadresse: (?<deliveryAdress>.*)$ [\s\S]*?^Referenz: (?<reference>.*)$ [\s\S]*?^Lademittel: (?<loading>.*)$ [\s\S]*?^Plombennummer: (?<plombe>.*)$ [\s\S]*?^Bemerkung: (?<remarks>.*)$", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace); // 直接通过分组名取值即可 var deliveryAddress = matchResult.Groups["deliveryAdress"].Value; var reference = matchResult.Groups["reference"].Value;
这里的[\s\S]*?是非贪婪匹配任意字符(包括换行),会自动跳过两个目标字段之间的无关行,不会吞掉后续字段的匹配内容。
注意:该方案要求所有目标字段必须在文本中存在,且严格按照正则里写的顺序出现,否则会匹配失败。
方案2:遍历现有匹配结果聚合(推荐)
不需要修改你已经写好的正则,只要遍历Matches返回的所有结果,把每个匹配命中的分组值聚合到同一个字典/模型对象里即可,容错性更高,就算某个字段缺失、字段顺序变动也不会整体失效:
var extractedData = new Dictionary<string, string>(); var matches = Regex.Matches( pageText, "^Ort Lieferadresse: (?<deliveryAdress>.*)$|^Referenz: (?<reference>.*)$|^Lademittel: (?<loading>.*)$|^Plombennummer: (?<plombe>.*)$|^Bemerkung: (?<remarks>.*)$", RegexOptions.Multiline); foreach (Match singleMatch in matches) { if (singleMatch.Groups["deliveryAdress"].Success) extractedData[nameof(deliveryAdress)] = singleMatch.Groups["deliveryAdress"].Value; if (singleMatch.Groups["reference"].Success) extractedData[nameof(reference)] = singleMatch.Groups["reference"].Value; if (singleMatch.Groups["loading"].Success) extractedData[nameof(loading)] = singleMatch.Groups["loading"].Value; if (singleMatch.Groups["plombe"].Success) extractedData[nameof(plombe)] = singleMatch.Groups["plombe"].Value; if (singleMatch.Groups["remarks"].Success) extractedData[nameof(remarks)] = singleMatch.Groups["remarks"].Value; }
针对你提供的样例文本,两种方案最终提取到的结果一致:
- deliveryAdress:Foo
- reference:Bar
- loading:40' Container
- plombe:keine, da Abholung im LKW
- remarks:Kennzeichen: AB12345 / CD67890
实际生产场景优先选方案2,后续如果要新增提取的键值对,只需要在正则里加一个分支、在遍历逻辑里加一个分组判断即可,维护成本低,也不会因为文本格式的小变动导致整个提取逻辑失效。
内容的提问来源于stack exchange,提问作者André Reichelt
相关产品推荐
相关产品推荐

