【问题标题】:C# reliable way to pattern match?C#可靠的模式匹配方法?
【发布时间】:2010-01-26 14:08:29
【问题描述】:

目前我正在尝试匹配诸如

之类的模式

text text date1 date2

所以我有正则表达式可以做到这一点。但是,问题是,例如,如果用户输入的数据有超过 1 个空格,或者如果他们将一些文本放在新行中等,则模式不会被拾取,因为它不完全正确匹配模式集。

有没有更可靠的模式匹配方法?我们的目标是让用户编写起来非常简单,但在我的终端上也很容易匹配。我正在考虑删除所有空格/换行符等,然后尝试匹配没有空格的模式,即texttextdate1date2

谁有更好的解决方案?

更新

这是我需要匹配的模式的一个小例子:

FIND me@test.com 01/01/2010 to 10/01/2010

这是我当前的正则表达式:

FIND [A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4} [0-9]{1,2}/[0-9]{1,2}/[0-9]{2,4} to [0-9]{1,2}/[0-9]{1,2}/[0-9]{2,4}

这在 90% 的情况下都可以正常工作,但是,如果用户通过电子邮件提交此信息,它可能具有我不感兴趣的所有不同类型的格式和 HTML。我正在使用 HtmlAgilityPack 和 HTML 的组合标记删除正则表达式以从电子邮件中删除所有 HTML,但即便如此,我似乎在某些情况下也无法匹配。

我相信这可能是一个比模式匹配更与解析相关的问题,但我认为也许有更好的方法来做到这一点......

【问题讨论】:

  • 用一个正则表达式匹配多个空格绝对没有问题。向我们展示该模式,您将获得新的作为回报。 :)
  • @Jonas,正则表达式确实与空格匹配得很好,我已经有一个可以解决问题的。我的问题是我遇到了有时信息位于不同行等的情况,或者用户可能错误地在文本之间输入了几个额外的不需要的空格。我希望能够处理这些情况。
  • @James,请发布您正在使用的正则表达式。
  • 正确的正则表达式查询可以轻松处理这些情况
  • @James 如果你想匹配一个电子邮件地址,你的正则表达式应该支持标准 (tools.ietf.org/html/rfc2822#section-3.4.1) - 这里有一个例子:regular-expressions.info/email.html

标签: c# regex parsing


【解决方案1】:

要匹配至少一个或多个空白字符(空格、制表符、换行符),请使用:

\s+

在您的模式中有物理空间的任何地方替换上述内容,您应该没问题。

【讨论】:

  • 我想这可能就是我所缺少的。我会调整我的正则表达式,看看它是否有效!
  • 有没有办法确定和检测您找到了哪种类型的空白?
【解决方案2】:

将文本中的多个组与多个空格和/或换行符匹配的示例。

var txt = "text text   date1\ndate2";
var matches = Regex.Match(txt, @"([a-z]+)\s+([a-z]+)\s+([a-z0-9]+)\s+([a-z0-9]+)", RegexOptions.Singleline);

matches.Groups[n].Value 中的 n 从 1 到 4 将包含您的匹配项。

【讨论】:

    【解决方案3】:

    我会将字符串拆分为一个字符串数组,并将每个结果字符串与必要的正则表达式进行匹配。

    【讨论】:

      【解决方案4】:
      \b(text)[\s]+(text)[\s]+(date1)[\s]+(date2)\b
      

      【讨论】:

        【解决方案5】:

        这是一个令人讨厌的表达方式,但以下内容适用于您提供的输入:

        ^(\w+)\s+([\w@.]+)\s+(\d{2}\/\d{2}\/\d{4})[^\d]+(\d{2}\/\d{2}\/\d{4})$

        这也适用于捕获组之间的可变数量的空白。

        【讨论】:

        • 不正确,恐怕\w@以及任何空白字符(\n除外)和后面的数字都会被.匹配,基本上是贪婪匹配。使用? 后缀进行非贪婪匹配。
        • . 是字符类的成员,因此它不代表元字符,而是文字值 "."
        【解决方案6】:

        通过 ORegex,您可以对字符串进行标记,并在标记序列上进行模式匹配:

        var tokens = input.Split(new[]{' ','\t','\n','\r'}, StringSplitOptions.RemoveEmptyEntries);
        var oregex = new ORegex<string>("{0}{0}{1}{1}", IsText, IsDate);
        
        var matches = oregex.Matches(tokens); //here is your subsequence tokens.
        
        ...
        
        public bool IsText(string str)
        {
            ...
        }
        
        public bool IsDate(string str)
        {
            ...
        }
        

        【讨论】:

          猜你喜欢
          • 2012-12-17
          • 1970-01-01
          • 1970-01-01
          • 2021-02-02
          • 1970-01-01
          • 2014-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多