正则表达式匹配但忽略输出中的特定字符

时间:2014-10-01 19:11:51

标签: c# regex string-parsing

我需要一个正则表达式PATTERN(将在C#中使用),它将匹配整数值 WITH 3位逗号分隔符但 WON' T 在结果匹配值中返回逗号。例如,我需要以下代码将112341234567写入控制台:

string text = "This 1 is 1,234 a 1,234,567 sentence 7,654.321.";
// NOTE: value "7,654.321" would preferably NOT match, 
//       but it is acceptable for now if it does
MatchCollection matches = Regex.Matches(text, PATTERN);
foreach (Match match in matches)
    Console.Write(match.Value + " ");

无法致电Regex.Matches,然后执行String.Replace删除逗号;这一切都必须发生在正则表达式PATTERN中(因为我的所有正则表达式都是从数据库中提取的,并且在没有大量意大利面条代码的情况下不能包含模式本身之外的逻辑)。如上所述,我宁愿不匹配理性值,但是一旦我将逗号排除工作,这应该很容易解决。

以下模式不工作,但它可能非常接近我的需要:

// THIS PATTEN DOES NOT WORK!!!
//    but is probably close to what I need
string PATTERN = @"([\+-]?[0-9]+[(?<=,)[0,9]{3}]*)([eE][\+]?[0-9]+)?"

如果从上方删除[(?<=,)[0,9]{3}]*,则表示您具有标准整数模式。我需要再次接受整数中的逗号,但不要将它们作为匹配的一部分返回。我该如何改变这种模式?

1 个答案:

答案 0 :(得分:0)

正则表达式匹配输入字符串的整个子字符串。它不能是一组子串 - 它必须是一个子串。

同样,捕获组只能捕获子串,因此您也无法做到这一点。

但是,既然您正在使用.NET,那么如果您能够负担得起一些通用代码,那么您可以通过利用捕获堆栈来尝试真正的丑陋黑客攻击。

首先是正则表达式。它被简化为最小化,因此更容易理解:

(?:(?<concat>\d+),?)+

下面提供了正则表达式的完整版本,但是现在我们将坚持使用该版本。

然后,在您的代码中,您可以实现以下逻辑:

  • 如果正则表达式不包含名为concat的组,则照常处理
  • 如果是,请执行以下操作,而不是获取整个匹配:
    • 提取该群组的所有抓取:match.Groups["concat"].Captures
    • Concat他们捕获的值
    • 然后使用该值

这与此类似:

public static IEnumerable<string> GetValues(string input)
{
    // Suppose regex could be any regex
    var regex = new Regex(@"(?:(?<concat>\d+),?)+");

    foreach (Match match in regex.Matches(input))
    {
        // Does this regex have our special feature?
        if (regex.GroupNumberFromName("concat") >= 0)
        {
            // Concat the captured values
            var captures = match.Groups["concat"].Captures.Cast<Capture>().Select(c => c.Value).ToArray();
            yield return String.Concat(captures);
        }
        else
        {
            // This is a normal regex
            yield return match.Value;   
        }
    }
}

Ideone demo

好的,这是一个hack,但它会让你在正则表达式中以声明性和可重用的方式保持逻辑。

现在,您发布的完整正则表达式在其黑客版本中看起来像这样:

(?<concat>[-+])?(?<concat>[0-9]+)(?:,(?<concat>[0-9]{3}))*(?<concat>[eE][-+]?[0-9]+)?

Demo