.NET Regex - 获取与模式不匹配的字符串部分

时间:2017-11-21 19:21:41

标签: c# regex

我有这个字符串

TEST_TEXT_ONE_20112017

我想消除_20112017,这是一个带数字的下划线,这些数字可能会有所不同;我的目标是只有

TEST_TEXT_ONE

到目前为止,我有这个,但我得到了整个字符串,是否有我遗漏的东西?

Regex r = new Regex(@"\b\w+[0-9]+\b");
MatchCollection words = r.Matches("TEST_TEXT_ONE_20112017");

foreach(Match word in words)
{
   string w = word.Groups[0].Value;
   //I still get the entire string
}

3 个答案:

答案 0 :(得分:3)

供您考虑的注意事项:

  1. 您应该使用括号标记捕获组或使用命名组。第一组(index = 0)是整个匹配。你可能想要index = 1。
  2. \w代表word character,它已包含下划线和数字。如果您想在数字之前匹配任何内容,那么您应该考虑使用.代替\w
  3. 默认情况下+是贪婪的,而您的\w+将消耗您的最后一个非核心,除了最后一个号码之外的所有非核心消息。您可能希望在最后一个数字块之前明确要求下划线。
  4. 我建议您考虑是否要找到匹配的子字符串或整个字符串来匹配。如果是后者,则考虑使用开始和结束标记:^$
  5. 如果您知道要消除8位数,那么您可以给出明确的计数,例如\d{8}
  6. 例如,这应该有效:

    Regex r = new Regex(@"^(.+)_\d+$");
    MatchCollection words = r.Matches("TEST_TEXT_ONE_20112017");
    foreach (Match word in words)
    {
        string w = word.Groups[1].Value;
    }
    

    <强>替代

    使用Zero-Width Positive Lookahead Assertions构造来检查接下来会发生什么而不捕获它。这使用(?=stuff)上的语法。所以你可以使用更短的代码,避免在群组中冲浪:

    Regex r = new Regex(@"^.+(?=_\d+$)");
    String result = r.Match("TEST_TEXT_ONE_20112017").Value;
    

    请注意,我们需要在正向前方组中使用结束标记$

答案 1 :(得分:1)

Regex r = new Regex(@"(\b.+)_([0-9]+)\b");
String w = r.Match("TEST_TEXT_ONE_20112017").Groups[1].Value; //TEST_TEXT_ONE

或:

String w = r.Match("TEST_TEXT_ONE_20112017").Groups[2].Value; //20112017

答案 2 :(得分:1)

在我看来,对于Regex来说这似乎有点过分了。作为替代方案,您可以拆分_字符并重建字符串:

private static string RemoveDate(string input)
{
    string[] parts = input.Split('_');      
    return string.Join("_", parts.Take(parts.Length - 1));
}

或者,如果日期后缀的长度始终相同,那么 也只是子字符串:

private static string RemoveDateFixedLength(string input)
{
    //Removes last 9 characters (8 for date, 1 for underscore)
    return input.Substring(0, input.Length - 9);
}

但是我觉得第一种方法更好,这只是另一种选择。

小提琴here