2010-09-24 34 views
7

polygenelubricants 'ifadesinin ruhuyla, düzenli ifadelerle aptalca şeyler yapma, Şu anda benim için çoğaltmak üzere .NET regex motorunu almaya çalışıyorum. Bu, elbette pratik bir değere sahip değildir ve tamamen teorik bir alıştırma olarak kastedilmektedir. Şimdiye kadar, bu canavara ulaştım, bu 1s sayısının 2s ile çarpılmasının dizideki 3s sayısına eşit olup olmadığını kontrol etmelidir..NET düzenli ifadelerle çarpma

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); 

Ne yazık ki, çalışmıyor ve neden bir kayıp yaşıyorum. Motorun ne yapması gerektiğini düşündüğümü size anlattım, ama burada olabilirim. çıktı örnekler:

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

Herhangi bir düşünce bekliyoruz!

cevap

1

Sorun bu satırda eminim: Orada maç için hiçbir metin ile, söyleyebileceğim

(?<b-c>)* 

, Regex o birden çok kez maç reddeder. şuna Regex zayıflayan:

1 geçer ama 111 üzerinde başarısız
(1(?<a>))* 
(?(a)(?<-a>))* 
(?(a)(?!)) 

. Ayrıca (?<-a>)* çalıştı. Fark yok. Bununla birlikte,

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

değiştirmeyi 12 ve 111222 hem de geçer. Yani bir eşleşme ile bir maç için "" bir maç gidiş, Regex beklendiği gibi çalışmasına neden olur.

Orijinal Regex'inize dönecek olursak, tahminim (?<b-c>)* yalnızca 0-1 çarpı ile eşleşiyor, bu da dizinizde bir 2'nin neden çalıştığını açıklıyor, ancak birden fazla başarısız oluyor. Bu büyük olasılıkla (?(a)(?!)) başarısız olmasına neden, sadece bir defa maçları anlamına tüm maç "", yapar gibi 11 bir dizi kullanarak

da aynı mantığı izler, hangi başarısız olur.

+0

Güzel analiz, teşekkürler! Bunu düzeltip düzeltemeyeceğimi göreceğim ... =) – Jens

0

Joel'in girdisiyle, bu (?<b-c>)* satırlarından kaçınmak için algoritmayı hafifçe değiştirmeyi başardım.

Bakın:

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); 

Bir ideone linki vermek istiyorum ama olsun sonuç madenden orada farklıdır. Belki .NET 4.0 kullanıyorum ve yapmıyorlar?

+0

Bu hala '11' durumunda başarısız oluyor, ancak bunun için başka bir başarısızlık durumu bulamadım. –