【问题标题】:C# Regex string parsingC# 正则表达式字符串解析
【发布时间】:2012-10-04 12:41:39
【问题描述】:

我已经编写了表达式,但是每当我运行代码时,我都会得到整个字符串和一大堆空值:

Regex regex = new Regex(@"y=\([0-9]\)\([0-9]\)(\s|)\+(\s+|)[0-9]");
Match match = regex.Match("y=(4)(5)+6");

for (int i = 0; i < match.Length; i++)
{
    MessageBox.Show(i+"---"+match.Groups[i].Value);
}

预期输出:4、5、6(在不同的 MessageBox 中

实际输出:y=(4)(5)+6

它会检查输入的字符串是否正确,但一旦正确,我就无法获得具体的值(4、5 和 6)。我该怎么做才能获得该代码?这可能是非常简单的事情,但我已经尝试查看 MSDN match.NextMatch 文章,但这似乎也没有帮助。

谢谢!

【问题讨论】:

  • 我不太明白这个问题 - 您是否正在寻找正则表达式来匹配格式不正确的字符串?
  • 正则表达式匹配字符串很好 - 当所有变量都被填充时,它返回 true(或 match.Success)。但是,获得每个单独的值是我所追求的。
  • 您是否尝试过检查 .Captures ? msdn.microsoft.com/en-us/library/twcw2f1c.aspx

标签: c# .net regex


【解决方案1】:

目前,您没有指定任何组。 (除了周围的空间。)

您可以使用括号指定组。您当前使用的括号带有反斜杠,因此它们被用作匹配的一部分。在其中添加一组额外的括号。

像这样:

new Regex(@"y=\(([0-9]+)\)\(([0-9]+)\)\+([0-9]+)");

还有空格:

new Regex(@"y\s*=\s*\(([0-9]+)\)\s*\(([0-9]+)\)\s*\+\s*([0-9]+)");

这也将允许部分之间的空格是可选的,因为 * 表示 0 或更多。这比上面给出的 (?:\s+|) 更好,因为您不需要为空格设置一个组。它也更好,因为管道的意思是“或”。你在说什么 \s+|是“一个或多个空格或什么都没有”。这与 \s* 相同,即“零个或多个空格”。

另外,我使用了 [0-9]+,因为这意味着 1 个或多个数字。这允许匹配具有多个数字的数字,例如 10 或 100。另一个注意事项,使用 [0-9] 比 \d 更好,因为 \d 不仅仅指我们习惯的数字。

【讨论】:

  • 刚刚更新了我的答案,使其更加清晰。希望您现在了解模式的每个部分在做什么。
【解决方案2】:

使用(命名的)捕获组。对于您不想想要捕获的组,您还需要使用(?:) 而不是()。否则,它们也会在结果组中。

Regex regex = new Regex(@"y=(\([0-9]\))((\([0-9]\))(?:\s|)\+(?:\s+|)([0-9])");
Match match = regex.Match("y=(4)(5)+6");
Console.WriteLine("1: " + match.Groups[1] + ", 2: " + match.Groups[2] + ", 3: " + match.Groups[3]);

如果模式找到匹配项,则该匹配项的组被写入属性,该属性可以通过索引访问(索引0 包含完整匹配项)。

您还可以为这些组命名以获得更具可读性的代码:

Regex regex = new Regex(@"y=(?<first>\([0-9]\))(?<second>(\([0-9]\))(?:\s|)\+(?:\s+|)(?<third>[0-9])");

现在,您可以使用match.Groups["first"] 等方式访问捕获组。

【讨论】:

    【解决方案3】:

    您需要为您的群组命名,以便稍后将其拉出。 How do I access named capturing groups in a .NET Regex?

    Regex regex = new Regex(@"y=\((?<left\>[0-9])\)\((?<right>[0-9])\)(\s|)\+(\s+|)(?<offset>[0-9])");
    

    然后你可以像这样把它们拉出来:

    regex.Match("y=(4)(5)+6").Groups["left"];
    

    【讨论】:

      【解决方案4】:

      C# 超出了我的专业领域,但这可能有效:

      @"y=\(([0-9])\)\(([0-9])\)(?:\s|)\+(?:\s+|)([0-9])"
      

      这基本上是您的原始正则表达式,但在数字周围捕获组,并且将不需要的捕获组更改为非捕获组:(?: ... )

      【讨论】:

        【解决方案5】:

        Group[0] 将始终为您提供匹配的字符串,空值来自 (\s|)。

        这将起作用:y=\((\d)\)\((\d)\)\s*\+\s*(\d)

        从 1 开始计算您使用的括号的组,但如果您将它们转义,则它们不计算在内(因为您告诉它它们只是要匹配的文本),因此这些数字需要自己的括号。在类似的情况下使用(x|) 也不是一个好主意?或 * 会更合适,因为你没有捕捉到那个位。

        这可能会更好y=\((\d+)\)\((\d+)\)\s*\+\s*(\d+),因为它支持大于十的值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-29
          • 2012-08-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-25
          相关资源
          最近更新 更多