【问题标题】:C#: Determing if string is like this pattern; possible regexC#:确定字符串是否像这种模式;可能的正则表达式
【发布时间】:2016-07-20 17:17:30
【问题描述】:

考虑一个如下所示的字符串:

RR1 S5 C92

这是用于外地邮件递送的农村路线地址:农村路线、站点、隔间。每个字母后跟一个数字和一个空格。通常长一到三位数,但你永远不知道它可能是多少个数字!如果用户是懒惰的,他们可能输入了零个、一个或多个空格。

问题: 您将使用什么正则表达式来确定给定的字符串是否与此模式匹配?

它的用法是这样的:

string ruralPattern; //a regex pattern here
bool isRural = Regex.Match(someString, ruralPattern);

更新:感谢您的建议!性能和使用情况将在要从 Web 服务调用的程序集中的静态方法中。根据此模式检查的字符串最多为 50 个字符。该方法将大约每 5 秒调用一次。关于保持静态的任何建议?非常感谢!

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    这应该可行:

    ^[Rr][Rr]\d+ *[Ss]\d+ *[Cc]\d+$
    

    或根据其他评论

    ^[Rr][Rr][0-9]+ *[Ss][0-9]+ *[Cc][0-9]+$
    

    这意味着什么:

    • ^ - 字符串开头
    • [Rr] - 下一个字符必须是 R 或 r
    • [Rr] - 下一个字符必须是 R 或 r
    • \d+ 或 [0-9]+ - 下一部分必须是 1 个或多个数字
    • (空格)* - 允许 0 个或更多空格
    • [Ss] - 下一个字符必须是 S 或 s
    • \d+ 或 [0-9]+ - 下一部分必须是 1 个或多个数字
    • (空格)* - 允许 0 个或更多空格
    • [Cc] - 下一个字符必须是 C 或 c
    • \d+ 或 [0-9]+ - 下一部分必须是 1 个或多个数字
    • $ - 字符串结尾

    可能有更优雅的解决方案,但这很容易阅读。

    编辑:已更新以包含来自某些 cmets 的输入

    【讨论】:

    • 当然...我希望更多的人能像我上面所说的那样分解他们的解决方案,以使它们更容易理解,因为正则表达式不是最易读的语法。
    • @Kelsey:感谢您解释正则表达式语法
    【解决方案2】:

    怎么样...

    someString = someString.Trim(); // eliminate leading/trailing whitespace
    bool isRural = Regex.Match(
       someString,
       @"^rr\d+\s*s\d+\s*c\d+$",
       RegexOptions.IgnoreCase);
    

    这消除了模式中的大写/小写切换,并使用\s 允许任何(非换行符)空白字符(例如制表符)。如果只需要空格,则应将'\s' 更改为' '

    【讨论】:

    • +1,这是迄今为止最简单和最正确的答案,但是,请注意\d 不仅仅匹配[0-9]。它匹配 char.IsDigit 返回 true 的任何字符,据我统计,它包括一些 230 个 unicode 代码点。
    • 是的,确实如此,可以为\s (char.IsWhiteSpace) 提出类似的声明。
    【解决方案3】:

    让我们澄清以下假设:

    1. 字符串分为三个部分。
    2. 第 1 部分始终以 RR 大写或小写字母开头,并以一位或多位十进制数字结尾。
    3. 第 2 部分始终以 S 大写或小写字母开头,并以一位或多位十进制数字结尾。
    4. 第 3 部分始终以 C 大写或小写字母开头,并以一位或多位十进制数字结尾。

    为简单起见,以下内容就足够了。

    [Rr][Rr][0-9]+[ ]+[Ss][0-9]+[ ]+[Cc][0-9]+
    
    1. [Rr] 表示恰好一个字母 R, 大写或小写。
    2. [0-9] 表示正好一位小数 数字。
    3. [0-9]+ 表示至少一个或多个, 十进制数字。
    4. [ ]+ 表示至少一个或多个, 空格。

    但是,为了有用,通常,当您使用正则表达式时,我们还会检测各个部分以利用匹配功能来帮助我们将各个部分值分配给它们各自/各个变量。

    因此,下面的正则表达式更有帮助。

    ([Rr][Rr][0-9]+)[ ]+([Ss][0-9]+)[ ]+([Cc][0-9]+)
    

    让我们将该正则表达式应用于字符串

    string inputstr = "Holy Cow RR12 S53 C21";
    

    这是您的正则表达式匹配器会告诉您的:

    start pos=9, end pos=21
    Group(0) = Rr12 S53 C21
    Group(1) = Rr12
    Group(2) = S53
    Group(3) = C21
    

    一共有三对椭圆/圆括号。 每对都是字符串的一部分,正则表达式编译器将其称为一个组。

    正则表达式编译器会调用匹配的

    1. 作为组 0 的整个匹配字符串
    2. 乡村路线作为第 1 组
    3. 站点为第 2 组和
    4. 隔间作为第 3 组。

    当且仅当第 0 组有匹配时,第 1、2 和 3 组自然会遇到匹配。

    因此,您的算法将使用以下伪代码利用它

    string postalstr, rroute, site, compart;
    if (match.group(0)!=null)
    {
      int start = match.start(0);
      int end = match.end(0);
      postalstr = inputstr.substring(start, end);
    
      start = match.start(1);
      end = match.end(1);
      rroute = inputstr.substring(start, end);
    
      start = match.start(2);
      end = match.end(2);
      site = inputstr.substring(start, end);
    
      start = match.start(3);
      end = match.end(3);
      compart = inputstr.substring(start, end);
    }
    

    此外,您可能希望输入包含以下列的数据库表:rr、site、compart,但您只想输入不带字母“rr”、“s”或“c”的数字。 这将是使用嵌套分组的正则表达式。

    ([Rr][Rr]([0-9]+))[ ]+([Ss]([0-9]+))[ ]+([Cc]([0-9]+))
    

    当第 0 组发生匹配时,匹配器会通知您以下信息:

    start=9, end=21
    Group(0) = Rr12 S53 C21
    Group(1) = Rr12
    Group(2) = 12
    Group(3) = S53
    Group(4) = 53
    Group(5) = C21
    Group(6) = 21
    

    【讨论】:

      【解决方案4】:

      仅供参考:如果您要使用此 RegEx 来测试大量数据,最好的办法是告诉 .NET 对其进行预编译 - 它将被编译成 IL 并提高性能,而不是简单地每次都解释正则表达式模式。将其指定为包含您的方法的任何类的静态成员,如下所示:

      private static Regex re = new Regex("pattern", RegexOptions.Compiled | RegexOptions.IgnoreCase);
      

      ...而测试字符串是否匹配模式的方法是...

      bool matchesString = re.IsMatch("string");
      

      祝你好运。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多