2010-09-24 52 views
7

本着polygenelubricants'努力用正则表达式来做愚蠢的事情, 我当前尝试让.NET正则表达式引擎为我乘法。与.NET正则表达式相乘

这当然没有实用价值,而是纯粹的理论练习。

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

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 

任何想法都欢迎!

回答

1

我敢肯定,这个问题是在这一行:

(?<b-c>)* 

从我可以告诉,没有文字在那里进行匹配,正则表达式拒绝一个以上的时间相匹配。 我瘦身的正则表达式如下:

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

其中传递1但未能上111。也试过(?<-a>)*。没有不同。然而,将其更改为

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

经过两个12111222。因此,从""的比赛到与某事匹配导致正则表达式按预期工作。

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

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

+0

尼斯分析,谢谢!我会看看我是否可以解决这个问题...... =) – Jens 2010-09-27 06:16:09

0

有了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而他们不?

+0

这在'11'情况下仍然失败,但我还没有发现它的另一个失败案例。 – 2010-09-27 15:57:46