【问题标题】:Conditional .NET regex条件 .NET 正则表达式
【发布时间】:2014-07-22 13:09:30
【问题描述】:

我想编写一个名为 IsStrValid 的 F#.NET 布尔函数,使用正则表达式来确定给定字符串 s 是否符合以下规则:

  • s 长度为 4 个字符
  • 第一个和第三个字符是 A、B 或 C
  • 第二个字符是 1、2 或 3
  • 第 4 个字符是 1、2 或 3,除非第 1 个和第 3 个字符相同 - 那么第 4 个字符不能与第 2 个相同。

例如:

IsStrValid "A3B3" //true
IsStrValid "A3A3" //false

这就是我已经走了多远;卡在条件部分(???):

let IsStrValid (s : string) =   
    Regex.IsMatch(s, @"^([ABC])([123])([ABC])(?(???)[123]|[???])$")

【问题讨论】:

  • 如果没有正则表达式,这可能会容易得多。

标签: .net regex f# conditional


【解决方案1】:

虽然正则表达式支持backreferences,但尝试执行“如果 X 则 Y”之类的复杂逻辑非常困难。你可以用negative lookahead 断言来做这样的事情:

let IsStrValid (s : string) = 
    Regex.IsMatch(s, @"^([ABC][123])(?!\1)[ABC][123]$")

但是,作为 Mathew suggests,如果它变得比这更复杂,那么直接测试条件可能更容易,如下所示:

let IsStrValid (s : string) =
    let isLet i = Seq.exists ((=)s.[i]) ['A'; 'B'; 'C']
    let isNum i = Seq.exists ((=)s.[i]) ['1'; '2'; '3']
    (s.Length = 4) && (isLet 0) && (isNum 1) && (isLet 2) && (isNum 3) &&
    (s.[0] <> s.[2]) || (s.[1] <> s.[3]) 

【讨论】:

    【解决方案2】:

    这听起来像是条件语句的完美应用,但它们实际上使这项工作变得更加困难,而不是更少。使用前瞻的老式方法要容易得多。

    ^
    ([ABC])
    ([123])
    (?:
       (?!\1)[ABC][123]
     |
       \1(?!\2)[123]
    )
    $
    

    这几乎一字不差地实现了您的描述。如果第三个字符是允许的字母之一,但与第一个不同,则抓住它和任何允许的数字。如果第三个字符与第一个字符相同,则抓住它后跟一个允许的数字,除非它与第一个数字相同。

    但我认为即使这样也比它需要的更复杂。在我看来,您的要求可以重述为与正则表达式 [ABC][123] 匹配的两对连续字符,但不能相互匹配

    ^([ABC])([123])(?!\1\2)[ABC][123]$
    

    【讨论】:

      【解决方案3】:

      我同意 Matthew 的观点,即没有理由为此使用正则表达式。然而,这当然是可能的,即使没有反向引用。首先,有一组有限的字符串,所以你可以把它们全部列出来(或者写一个简单的函数来生成这个字符串):

      A1A2|A1A3|A1B1|A1B2|...
      

      但是想出一个稍微不那么荒谬的方法也很容易。您要求第一个和第三个字符不同,或者第二个和第四个字符不同(或两者都不同),因此您可以明确写出(使用RegexOptions.IgnorePatternWhitespace):

      [A-C]1[A-C](2|3) |
      [A-C]2[A-C](1|3) |
      [A-C]3[A-C](2|3) |
      A[1-3](B|C)[1-3] |
      B[1-3](A|C)[1-3] |
      C[1-3](A|B)[1-3]
      

      或者您可以将其分组以排除一些重复:

      [A-C](1[A-C](2|3)|
            2[A-C](1|3)|
            3[A-C](1|2))|
      (A[1-3](B|C)|
       B[1-3](A|C)|
       C[1-3](A|B))[1-3]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多