使用RegEx匹配C#中的Month-Day

时间:2013-12-31 17:54:42

标签: c# regex date search

让我先说这是我对Regex和C#的新手,所以我仍然想弄明白。我也意识到正则表达式是一个需要时间去理解的深层主题。我已经做了一些研究来解决这个问题,但我没有足够的时间来正确研究正则表达式语法的艺术,因为我明天需要这个程序。 (不,这不是功课,这是我的工作)

我正在使用c#逐行搜索文本文件,我正在尝试使用Regex表达式来检查任何行是否包含MM-DD格式的当前月份的任何日期。 Regex表达式用于传递文件每一行的方法中。

以下是我目前使用的方法:

private bool CheckTransactionDates(string line)
{ 
   // in the actual code this is dynamically set based on other variables
   string month = "12";

   Regex regExPattern = new Regex(@"\s" + month + @"-\d(0[1-9]|[1-2][0-9]|3[0-1])\s");
   Match match = regExPattern.Match(line);

   return match.Success;
}

基本上我需要它匹配,如果它前面有一个空格,后跟一个空格。仅当它是当前月份(在这种情况下为12),连字符和月中的某一天(“12-01”应匹配但不匹配“12-99”)。连字符的两边应始终为2位数。

这个正则表达式(我唯一可以匹配的东西)可以使用,但也可以选择超出必要范围的项目:

Regex regExPattern = new Regex(@"\s" + month + @"-\d{2}\s");

我也没有成功地试过这个:

Regex regExPattern = new Regex(@"\s" + month + @"-\d[01-30]{2}\s");

有谁能告诉我需要改变什么来获得我需要的结果? 提前谢谢。

2 个答案:

答案 0 :(得分:4)

如果您只是需要查明该行是否包含任何有效匹配,则此类内容将起作用:

private bool CheckTransactionDates(string line)
{ 
   // in the actual code this is dynamically set based on other variables
   int month = DateTime.Now.Month;
   int daysInMonth = DateTime.DaysInMonth(DateTime.Today.Year, DateTime.Today.Month);

   Regex pattern = new Regex(string.Format(@"{0:00}-(?<DAY>[0123][0-9])", month));
   int day = 0;

   foreach (Match match in pattern.Matches(line))
   {
      if (int.TryParse(match.Groups["DAY"].Value, out day))
      {
         if (day <= daysInMonth)
         {
            return true;
         }
      }
   }

   return false;
}

以下是它的工作原理:

您确定要搜索的月份(此处,我使用当前月份)以及该月份的天数。

接下来,使用string.Format函数构建正则表达式模式,该函数放置左零填充月份,然后是破折号,然后是任意两位数字00到39 ({{ 1}}表示第一个数字,[0123]表示第二个数字。这缩小了正则表达式的匹配,但对于约会并不是最终的。围绕它的[0-9]会创建一个正则表达式组,以便稍后处理它。请注意,如果行以有效日期开头,我没有检查空格。您可以轻松地为模式添加空间,或根据您的特定需求修改模式。

接下来,我们在循环中检查该行((?<DAY>...))上的所有可能匹配项。

如果找到匹配,我们会尝试将其解析为整数(它应该始终有效,基于我们匹配的模式)。我们使用我们在模式中定义的匹配的pattern.Matches组。

将该匹配解析为整数DAY后,我们会检查该日是否为指定月份的有效数字。如果是,我们从函数返回true,因为我们找到了一个有效的日期。

最后,如果我们没有找到匹配项,或者没有匹配项有效,我们将从函数返回false(仅当我们之前没有返回true时)。

答案 1 :(得分:3)

需要注意的一点是\s匹配任何空格字符,而不仅仅是空格:

  

\ s匹配任何空白字符[\ r \ n \ t \ f]

然而,真正寻找空间的正则表达式不会像这样(12-\d{2})。但是,我必须和社区其他人一起讨论如何处理比赛。你需要经历每场比赛并用更好的方法验证日期:

var input = string.Format(
    " 11-20 2690 E 28.76 12-02 2468 E* 387.85{0}11-15 3610 E 29.34 12-87 2534 E",
    Environment.NewLine);

var pattern = string.Format(@" ({0}-\d{{2}}) ", DateTime.Now.ToString("MM"));
var lines = new List<string>();

foreach (var line in input.Split(new string[] { Environment.NewLine },
    StringSplitOptions.RemoveEmptyEntries))
{
    var m = Regex.Match(line, pattern);
    if (!m.Success)
    {
        continue;
    }

    DateTime dt;
    if (!DateTime.TryParseExact(m.Value.Trim(),
        "MM-dd",
        null,
        DateTimeStyles.None,
        out dt))
    {
        continue;
    }
    lines.Add(line);
}

我一次一行的原因是因为你可能需要知道哪条线是好的,什么线是坏的。我的逻辑可能与你需要的不完全相符但你可以很容易修改它。