代码之家  ›  专栏  ›  技术社区  ›  Jens

与.NET正则表达式相乘

  •  7
  • Jens  · 技术社区  · 14 年前

    本着 polygenelubricants “用正则表达式做傻事的努力, 我目前正在尝试让.NET regex引擎为我进行乘法运算。

    当然,这没有实际价值,只是一个纯粹的理论练习。

    到目前为止,我已经找到了这个怪物,它应该检查1s乘以2s的数目是否等于字符串中3s的数目。

    Regex regex = new Regex(
    @"
    ^
    (1(?<a>))*  # increment a for each 1
    (2(?<b>))*  # increment b for each 2
        (?(a)   # if a > 0
            (                   
                (?<-a>)             # decrement a
                (3(?<c-b>))*        # match 3's, decrementing b and incrementing c until
                                    # there are no 3's left or b is zero
                (?(b)(?!))          # if b != 0, fail
                (?<b-c>)*           # b = c, c = 0
            )
        )*      # repeat
    (?(a)(?!))  # if a != 0, fail
    (?(c)(?!))  # if c != 0, fail
    $
    ", RegexOptions.IgnorePatternWhitespace);
    

    不幸的是,它不起作用,我也不知为什么。我评论它是为了告诉你我认为发动机应该做什么,但我可能在这里。 输出示例:

    regex.IsMatch("123") // true, correct
    regex.IsMatch("22") // true, correct
    regex.IsMatch("12233") // false, incorrect
    regex.IsMatch("11233"); // true, correct
    

    欢迎有任何想法!

    2 回复  |  直到 14 年前
        1
  •  1
  •   Joel Rondeau    14 年前

    我很确定问题出在这一行:

    (?<b-c>)*
    

    据我所知,在没有文本匹配的情况下,regex拒绝多次匹配它。 我把正则表达式简化为:

    (1(?<a>))*
    (?(a)(?<-a>))*
    (?(a)(?!))
    

    传遍 1 但失败了 111 . 也试过 (?<-a>)* . 没有区别。但是,将其更改为

    (1(?<a>))*
    (?(a)((?<-a>)(2(?<b>))(?<-b>)))*
    (?(a)(?!))
    

    两通 12 111222 . 所以从一场比赛开始 "" 与某些内容匹配会导致regex按预期工作。

    回到你原来的Regex,我猜是 (?<b-c>)* 只匹配0-1次,这解释了为什么字符串中有一个2有效,但有多个失败。

    使用字符串 11 也会失败,这与使整个匹配的逻辑相同 ,这很可能意味着它只匹配一次,导致 (?(a)(?!)) 失败。

        2
  •  0
  •   Jens    14 年前

    有了Joel的输入,我就可以让它正常工作,稍微修改算法以避免这些问题。 (?<b-c>)* 线。

    看到:

    Regex regex = new Regex(
    @"
    ^
    (1(?<a>))*  # increment a for each 1
    (2(?<b>))*  # increment b for each 2
        (?(a)   # if a > 0
             (
                (?<-a>)             # decrement a
                (?(b)               # if b > 0
                    (                                       
                        (3(?<c-b>))*        # match 3's, decrementing b and incrementing c until
                                            # there are no 3's left or b is zero
                        (?(b)(?!))          # if b != 0, fail
                    )
                    |                       # else ( b = 0 )
                    (
                        (3(?<b-c>))*        # match 3's, decrementing c and incrementing b until
                                            # there are no 3's left or c is zero
                        (?(c)(?!))          # if c != 0, fail
                    )
                )
            )
        )*      # repeat
    (?(a)(?!))  # if a != 0, fail
    $
    ", RegexOptions.IgnorePatternWhitespace);
    

    我想给出一个IDeone链接,但是我得到的结果与我的不同。也许是因为我在使用.NET 4.0,而他们没有?