【问题标题】:Regex .net Only getting last match from line item list正则表达式 .net 仅从行项目列表中获取最后一个匹配项
【发布时间】:2018-12-12 20:29:52
【问题描述】:

我很少使用正则表达式。我正在尝试从字符串中获取零件号。到目前为止我花了一天时间。

我预计“Line”有 2 个匹配项

 __40X0343 1.00
 __C734X77G 2.00

在这些比赛中,我期待这些比赛

PartNo 40X0343 OrderQuantity 1.00 for Line 1
PartNo C734X77G OrderQuantity 2.00 for Line 2

但我只得到最后一场比赛,而不是两者。任何帮助都会很棒

正则表达式:

(?x)Required\sDate
(?<Line>__
(?<PartNo>[a-zA-Z0-9-]*)\S
(?<OrderQuantity>[0-9.]+)
)*

字符串

__Required Date__40X0343 1.00__C734X77G 2.00__Net Order:__Sales Tax:__Freight:__Order Total:__0.00 __0.00 __5,328.50 __5,328.50 __or by fax  

正则表达式工具的结果

Full match 2-44 `Required Date__40X0343 1.00__C734X77G 2.00` 
Group `Line` 29-44 `__C734X77G 2.00` 
Group `PartNo` 31-39 `C734X77G` 
Group `OrderQuantity` 40-44 `2.00` 

编辑以更好地说明我的问题

【问题讨论】:

  • 您能否进行编辑以更清晰地显示输入和预期输出。
  • 试试这个:(?__(?[a-zA-Z0-9-]+)\s(?[0-9.]+))+?。您将获得 2 场比赛。

标签: .net regex nsregularexpression


【解决方案1】:

这部分正则表达式 (?&lt;PartNo&gt;[a-zA-Z0-9-]*)\S 捕获一个名为 PartNo 的组,并匹配 [a-zA-Z0-9-]* 后跟 \S 匹配的不是空格字符,而是根据您的示例数据应该是 \s 匹配空白字符

因为你是repeating the capturing group,所以你只能得到最后一场比赛。

如果您希望有 2 个匹配项,您可以在与 PartNo 相同的组中捕获 OrderQuantity。

使用 C#,您可以使用 Group.Captures 并使用组名 PartNo。然后你可以获取捕获并循环它们。

例如:

string pattern = @"(?x)Required\sDate
(?<Line>__
(?<PartNo>[a-zA-Z0-9-]*\s[0-9.]+)
)*";
string str = @"__Required Date__40X0343 1.00__C734X77G 2.00__Net Order:__Sales Tax:__Freight:__Order Total:__0.00 __0.00 __5,328.50 __5,328.50 __or by fax";        
Regex regex = new Regex(pattern);
MatchCollection matchColl = regex.Matches(str);
if (matchColl != null) 
    foreach (Match match in matchColl) 
        foreach (Capture c in match.Groups["PartNo"].Captures) 
            Console.WriteLine(c.Value);

结果

40X0343 1.00
C734X77G 2.00

见C# demo

另一种选择是使用PartNo 和OrderQuantity regex demo 或不使用OrderQuantity 组regex demo 的多个命名捕获组

【讨论】:

  • 为什么我没有得到 2 场比赛?
  • 当我添加另一个行项目时,它不起作用。测试字符串-> __Required Date__40X0343 1.00__C734X7G 3.00__C734X77G 2.00__Net Order:__Sales Tax:__Freight:__Order Total:__0.00 __0.00 __5,328.50 __5,328.50 __或传真
  • @XGSDEV 那是因为现在你有 3 个组要捕获。如果您将 C# 代码与 Group.Captures 一起使用,它将工作 ideone.com/ycKEYG 还是您使用其他语言实时 VB.NET?
  • c#。我正在尝试为“Line”(不是捕获)获取匹配项,因此每行都可以使用“PartNo”和“OrderQuantity”。经过多次试验和错误,我过去曾有过类似的工作(在“线路”上匹配)
  • @XGSDEV 为了获得多个匹配项,您是否尝试使用 cmets 中建议的无限后视?您可以转到regexstorm.net/tester 并将其用作正则表达式(?x)(?&lt;=^__Required\sDate.*?) (?&lt;Line&gt;__ (?&lt;PartNo&gt;[a-zA-Z0-9-]*)\s (?&lt;OrderQuantity&gt;\d+(?:\.\d+)?) )*
【解决方案2】:

作为第一步,您似乎省略了重复语法,并且作为副产品,使之后更难捕获组。也就是说,这部分:

    (?<PartNo>[a-zA-Z0-9-]*)__

应该看起来更像这样:

    ((?<PartNo>[a-zA-Z0-9-]*)__)+

+ 表示您希望找到 1 个或多个,__ 包含在外部捕获组中,因为您需要它们一直延伸到最后一个部件号,并且非 __ 字符在他们自己的内部捕获组,因此您可以提取它们。

如果您确定总会有零件号,我会将? 放在内部捕获组中,从技术上讲它与+ 相矛盾,尽管当我尝试它时这似乎并不重要(在记事本++中),没有必要混淆这个问题。

您似乎需要对捕获组身份进行一些仔细的捕获后评估,虽然我不使用像 &lt;PartNo&gt; 这样的别名,所以我不能肯定地说,也许这并不难.

【讨论】:

  • 我的印象是 ?是命名捕获组语法的一部分
  • 你可能是对的,我不使用命名捕获,但看起来我的答案无论如何都被抛弃了。最后我会仔细研究一下那个语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 2013-12-01
  • 1970-01-01
  • 2016-01-11
  • 2017-11-17
相关资源
最近更新 更多