【问题标题】:.NET regex match returning too many elements.NET 正则表达式匹配返回太多元素
【发布时间】:2022-01-21 10:47:18
【问题描述】:

根据this question/answer,我使用以下正则表达式从括号中的数字解析name (100) 的名称,给出:

  1. 左方括号左侧的名称,去除左/右空格
  2. 括号中的数字

使用我的 C# 代码:

var found = Regex.Match("morleyc (1005)", @"(\S*)\s*\((\d*)", RegexOptions.IgnoreCase)

我得到一个包含 3 个项目的数组,而我希望一个 2 元素数组只包含第 2 个和第 3 个项目:

morleyc (1005
morleyc
1005

这是我所期望的(根据regexstorm.net 元素):

morleyc
1005

请告知我在代码中做错了什么?

.net 小提琴@https://dotnetfiddle.net/5DVWPs

【问题讨论】:

  • 可能是@"(\w+)\s*\([0-9]+\)" 模式,其中\w+ - 一个或多个单词(字母或数字)表示名称,然后\s* 表示可选空格,\([0-9]+\) 表示数字
  • 请参阅my answer to another question on this site 我尝试展示如何理解 C# 中正则表达式搜索的结果。

标签: c# .net regex


【解决方案1】:

也许,你想要

 @"(?<name>\w+)\s*\((?<number>[0-9]+)\)"

模式,在哪里

 \w+        - one or more word (letter or digit) characters for name
 \s*        - optional (zero or more) whitespaces
 \([0-9]+\) - one or more digits in parenthesis for number

注意命名捕获组

 (?<name> ... )    - part of the match which stands for name
 (?<number>  ... ) - -/- stands for number

如果名称只能包含字母(不允许使用数字),则可以输入

 @"(?<name>\p{L}+)\s*\((?<number>[0-9]+)\)"

pattern,其中\p{L} 代表一个unicode 字母

演示:

var found = Regex.Match(
  "morleyc (1005)", 
 @"(?<name>\w+)\s*\((?<number>[0-9]+)\)", 
   RegexOptions.IgnoreCase);
        
Console.WriteLine($"Name: {found.Groups["name"].Value}");
Console.WriteLine($"Number: {found.Groups["number"].Value}");

结果:

Name: morleyc
Number: 1005

Fiddle

【讨论】:

  • 感谢@Dmitry 的回复。您的小提琴给出了原始字符串和名称。我已更新我的问题以显示预期的输出元素(名称、编号)
  • @morleyc:我明白了;我已将 命名组 namenumber 添加到模式中,以便您轻松提取 morleys1005。我已经编辑了答案和小提琴。
【解决方案2】:

你做得对。根据.NET documentation

GroupCollection 对象的第一个元素(索引处的元素 0) Groups 属性返回的包含与 整个正则表达式模式

因此,具有 2 个组的正则表达式模式将返回 3 个结果:

  1. 匹配模式的字符串
  2. 第一组
  3. 第二组

【讨论】:

    【解决方案3】:

    结果中的morleyc (1005 部分是完整匹配。该模式也不匹配结束)

    您可以检查是否有匹配,如果有,则仅获取第 1 组和第 2 组的值。

    注意,在模式中,除了( 之外,几乎所有内容都是可选的,因此它也可以匹配单个(

    var found = Regex.Match("morleyc (1005)", @"(\S*)\s*\((\d*)\)", RegexOptions.IgnoreCase);
    if (found.Success) {
        Console.WriteLine(found.Groups[1].Value);
        Console.WriteLine(found.Groups[2].Value);
    }
    

    请参阅fiddle

    输出

    morleyc
    1005
    

    更具体的模式可能是:

    (\S+)[\p{Zs}\t]+\(([0-9]+)\)
    
    • (\S+) 捕获组 1,匹配 1+ 个非空白字符
    • [\p{Zs}\t]+ 匹配 1 个或多个空格(\s 也可以匹配换行符)
    • \(([0-9]+)\) 捕获组 2,匹配 () 之间的 1+ 个数字 0-9

    .NET regex demo

    【讨论】:

    • 感谢您的回复。根据我对文档的理解,它只会返回第二个和第三个元素......我可以跳过第一个元素,但如果我的正则表达式匹配正确,我似乎不需要这样做?
    • @morleyc 第一个元素是完全匹配,第二个是捕获组 1 的值,第三个是捕获组 2 的值。
    猜你喜欢
    • 2010-11-25
    • 1970-01-01
    • 2014-10-06
    • 2013-11-25
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    相关资源
    最近更新 更多