You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8正则表达式如何提取文本中首次出现的发票编号

.NET 8正则表达式如何提取文本中首次出现的发票编号

嗨,我来帮你搞定这个问题!你遇到的核心问题是正则的贪婪匹配在搞鬼——原来的表达式里的.*是贪婪模式,会一股脑匹配到文本里最后一个Invoice的位置,所以最终抓的是最后一个Invoice后面的payment,完全不是你要的顶部第一个发票号。

解决思路

要拿到文本最顶部(第一个出现的Invoice)后面的编号,我们只需要把开头的贪婪匹配.*改成非贪婪匹配.*?,同时确保正则从字符串开头开始匹配。这样它就会乖乖停在第一个Invoice的位置,而不会跳过前面的去抓后面的。

修改后的正则表达式

^(?si).*?Invoice[\s_:.]+(?<anr>[^\s_]+)

我来拆解一下关键调整:

  1. ^:强制从字符串的开头开始匹配,避免中间开始的干扰
  2. .*?:非贪婪匹配,只会匹配到第一个Invoice出现之前的内容,不会过度匹配
  3. 保留你原来的(?si)单行模式(让.匹配换行符)和编号提取逻辑(?<anr>[^\s_]+)

.NET 8代码示例

用C#代码实现的话,直接用Regex.Match就可以,不需要额外的特殊选项,调整正则就够了:

// 你的测试文本
var invoiceText = @"Payer:_xxxxxxx
Waybill Invoice_IN280625-3/4 Nimetus_EAN   
Invoice issuer: John
Selle Invoice tasumisel_palume m lisada Kesolev Invoice on poolte
vahel Invoice mittetähtaegsel tasumisel on müüjal õigus nõuda viivist 0,1% tasumata summalt päevas.
Kuni Invoice_IN280625-3/4 payment xxx";

// 编译正则(.NET 8里Regex默认是惰性编译,也可以用RegexOptions.Compiled)
var regex = new Regex(@"^(?si).*?Invoice[\s_:.]+(?<anr>[^\s_]+)");
var match = regex.Match(invoiceText);

if (match.Success)
{
    var invoiceNumber = match.Groups["anr"].Value;
    Console.WriteLine($"提取到的发票编号:{invoiceNumber}");
    // 输出结果就是:IN280625-3/4
}

为什么原来的正则不行?

再回头看你原来的表达式(?si).*Invoice[\s_:.]+(?<anr>[^\s_]+).+:

  • .*是贪婪匹配,会直接跳到文本最后一个Invoice的位置,所以后面抓的是最后一个Invoice后面的payment(因为payment符合[^\s_]+的规则)
  • 没有加^强制开头匹配,也没有用非贪婪模式,导致匹配逻辑完全跑偏

你问.NET 8的Regex.Match有没有专门的选项?其实真不需要——问题根源是正则的匹配逻辑,不是缺少API选项,调整正则的贪婪模式就完美解决了。

备注:内容来源于stack exchange,提问作者Andrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 10:03:12