^ Nb ^ n'yi Java regex ile nasıl eşleştirebiliriz?


99

Bu, bir dizi eğitici normal ifade makalesinin ikinci bölümüdür. Normal olmayan dil a n b n ile eşleşmek için bakma başlarının ve iç içe geçmiş referansların nasıl kullanılabileceğini gösterir . İç içe geçmiş başvurular ilk olarak şurada tanıtılır: Bu normal ifade üçgen sayıları nasıl bulur?

Düzenli olmayan arketip dillerden biri:

L = { an bn: n > 0 }

Bu, bir dizi a'nin ardından eşit sayıda' nin gelmesinden oluşan boş olmayan tüm dizelerin dilidir b. Bu dilde dizeleri örnekleri ab, aabb, aaabbb.

Bu dil, pompalanan lemma tarafından düzenli olmadığı gösterilebilir . Aslında bağlamdan bağımsız dilbilgisi ile oluşturulabilen arketipsel bir bağlamdan bağımsız dildir . S → aSb | ab

Bununla birlikte, günümüz normal ifade uygulamaları, normal dillerden daha fazlasını açıkça tanır. Yani, biçimsel dil teorisi tanımına göre "düzenli" değildirler. PCRE ve Perl, özyinelemeli regex'i destekler ve .NET, dengeleme grupları tanımını destekler. Daha az "süslü" özellikler, örneğin geri referans eşleşmesi, normal ifadenin düzenli olmadığı anlamına gelir.

Ancak bu "temel" özellikler ne kadar güçlü? LÖrneğin, Java regex ile tanıyabilir miyiz ? Belki lookarounds ve iç içe referanslar birleştirip örn eserler bu bir desen olabilir String.matchesgibi dizeleri eşleştirmek için ab, aabb, aaabbb, vs?

Referanslar

Bağlantılı sorular


4
Bu seri, topluluktaki bazılarının izni ile başlatıldı ( meta.stackexchange.com/questions/62695/… ). Alım iyiyse, normal ifadenin daha gelişmiş ve daha temel özelliklerini kapsamaya devam etmeyi planlıyorum.
polygenelubricants


Vay canına, Java'nın normal ifadelerinin normal ifadelerle sınırlı olmayacağını hiç bilmiyordum. Sanırım bu, neden her zaman tam olarak uygulanmayacağını düşündüğümü açıklıyor. Demek istediğim, Java Regex'lerinde yerleşik tamamlayıcı, fark veya ürün operatörü bulunmadığı, ancak Normal Dillerle sınırlı olmadıkları için bu mantıklı.
Lan

Bu soru, "Gelişmiş Regex-Fu" altındaki Yığın Taşması Normal İfadesi SSS bölümüne eklenmiştir .
aliteralmind

Yanıtlar:


141

Cevap, söylemeye gerek yok, EVET! Kesinlikle a n b n ile eşleşecek bir Java normal ifade kalıbı yazabilirsiniz . İddia için pozitif bir ilerleme ve "sayma" için iç içe geçmiş bir referans kullanır.

Bu cevap, kalıbı hemen vermek yerine, okuyuculara onu türetme sürecinde rehberlik edecektir . Çözüm yavaşça inşa edildiğinden çeşitli ipuçları verilmiştir. Bu açıdan, umarım bu yanıt başka bir düzgün düzenli ifade kalıbından çok daha fazlasını içerir. Umarım okuyucular, gelecekte kendi başlarına daha fazla kalıp türetebilmeleri için "normal ifadeyle düşünmeyi" ve çeşitli yapıları uyumlu bir şekilde bir araya getirmeyi öğreneceklerdir.

Çözümü geliştirmek için kullanılan dil, özlü olduğu için PHP olacaktır. Kalıp tamamlandıktan sonra son test Java'da yapılacaktır.


Adım 1: İddia için Önden Bakış

Biz maç için istiyorum: en basit sorunu ile başlayalım a+bir dize başında, ama hemen arkasından oluyor sadece b+. Biz kullanabilirsiniz ^etmek demirlemek bizim maçı ve sadece eşleştirmek istediğiniz beri a+olmadan b+kullanabileceğimiz ileriye dönük iddiayı (?=…).

İşte basit bir test koşum takımı içeren modelimiz:

function testAll($r, $tests) {
   foreach ($tests as $test) {
      $isMatch = preg_match($r, $test, $groups);
      $groupsJoined = join('|', $groups);
      print("$test $isMatch $groupsJoined\n");
   }
}
 
$tests = array('aaa', 'aaab', 'aaaxb', 'xaaab', 'b', 'abbb');
 
$r1 = '/^a+(?=b+)/';
#          └────┘
#         lookahead

testAll($r1, $tests);

Çıktı ( ideone.com'da görüldüğü gibi ):

aaa 0
aaab 1 aaa
aaaxb 0
xaaab 0
b 0
abbb 1 a

Bu tam olarak istediğimiz çıktıdır: a+yalnızca dizenin başındaysa ve hemen ardından gelirse eşleşiriz b+.

Ders : İddialarda bulunmak için bakma yöntemlerinde kalıpları kullanabilirsiniz.


Adım 2: Önden (ve serbest aralık modu) yakalama

Şimdi b+, maçın bir parçası olmasını istemesek bile , onu yine de 1. grupta yakalamak istiyoruz diyelim. Ayrıca, daha karmaşık bir model olmasını beklediğimiz xiçin, serbest boşluk için değiştirici kullanalım, bu yüzden normal ifademizi daha okunaklı hale getirebilir.

Önceki PHP parçacığımızı temel alarak, artık aşağıdaki kalıba sahibiz:

$r2 = '/ ^ a+ (?= (b+) ) /x';
#             │   └──┘ │
#             │     1  │
#             └────────┘
#              lookahead
 
testAll($r2, $tests);

Çıktı şimdi ( ideone.com'da görüldüğü gibi ):

aaa 0
aaab 1 aaa|b
aaaxb 0
xaaab 0
b 0
abbb 1 a|bbb

Örneğin aaa|b, joinher grubun yakaladığı şeyin -ing'in sonucu olduğunu unutmayın '|'. Bu durumda, grup 0 (yani modelin eşleştiği) aaave grup 1 yakalanır b.

Ders : Bir bakışta çekim yapabilirsiniz. Okunabilirliği artırmak için boş aralık kullanabilirsiniz.


3. Adım: Önden bakışı "döngü" içinde yeniden düzenleme

Sayma mekanizmamızı tanıtmadan önce, modelimizde bir değişiklik yapmamız gerekiyor. Şu anda, önden okuma +"döngü" tekrarının dışındadır . Bu var ki şu ana kadar sadece assert istedim çünkü gayet b+bizim şu a+, ama ne biz gerçekten en sonunda yapmak istediğiniz her biri için assert olur a, karşılık gelen var biz "döngü" içine eşleşmesini bonunla gitmek için.

Şimdilik sayma mekanizması hakkında endişelenmeyelim ve sadece aşağıdaki gibi yeniden düzenleme yapalım:

  • İlk yeniden a+düzenleme (?: a )+(bunun (?:…)yakalamayan bir grup olduğuna dikkat edin )
  • Ardından bakış açısını bu yakalamayan grubun içine taşıyın
    • Şimdi " a*görmeden " önce "atlamamız" gerektiğine dikkat edin b+, bu nedenle kalıbı buna göre değiştirin

Şimdi şunlara sahibiz:

$r3 = '/ ^ (?: a (?= a* (b+) ) )+ /x';
#          │     │      └──┘ │ │
#          │     │        1  │ │
#          │     └───────────┘ │
#          │       lookahead   │
#          └───────────────────┘
#           non-capturing group

Çıktı öncekiyle aynıdır ( ideone.com'da görüldüğü gibi ), bu nedenle bu konuda bir değişiklik yok. Önemli olan şimdi de iddiasını hale getirmesidir her yineleme arasında +"döngü". Mevcut modelimizle, bu gerekli değildir, ancak daha sonra kendi kendine referans kullanarak grup 1'i bizim için "sayarız".

Ders : Yakalamayan bir grubun içinde çekim yapabilirsiniz. Lookarounds tekrar edilebilir.


4. Adım: Bu, saymaya başladığımız adımdır

İşte yapacağımız şey: 1. grubu şu şekilde yeniden yazacağız:

  • İlk yinelemenin sonunda +, ilk aeşleştiğinde,b
  • İkinci yinelemenin sonunda, bir başkası aeşleştiğinde,bb
  • Üçüncü yinelemenin sonunda, bbb
  • ...
  • Sonunda , n -inci yineleme, grup 1 çekmeligüvenli b n
  • b1. gruba girmek için yeterli değilse , o zaman iddia başarısız olur

Dolayısıyla, şimdi olan 1. grup, (b+)benzer bir şeye yeniden yazılması gerekecek (\1 b). Yani, bönceki yinelemede yakalanan 1. gruba a "eklemeye" çalışıyoruz .

Burada, bu modelin "temel durumu", yani öz referans olmadan eşleşebileceği durumu, eksik olması nedeniyle küçük bir sorun var. Grup 1 "başlatılmamış" olarak başladığı için temel durum gereklidir; Henüz hiçbir şey yakalamadı (boş bir dizge bile), bu nedenle bir kendine referans girişimi her zaman başarısız olacaktır.

Bununla başa çıkmanın birçok yolu var, ancak şimdilik kendi kendine referans eşleştirmeyi isteğe bağlı yapalım , yani \1?. Bu mükemmel çalışabilir veya çalışmayabilir, ancak bunun ne işe yaradığını görelim ve herhangi bir sorun varsa, o zaman ona geldiğimizde o köprüyü geçeceğiz. Ayrıca, biz oradayken daha fazla test senaryosu ekleyeceğiz.

$tests = array(
  'aaa', 'aaab', 'aaaxb', 'xaaab', 'b', 'abbb', 'aabb', 'aaabbbbb', 'aaaaabbb'
);
 
$r4 = '/ ^ (?: a (?= a* (\1? b) ) )+ /x';
#          │     │      └─────┘ | │
#          │     │         1    | │
#          │     └──────────────┘ │
#          │         lookahead    │
#          └──────────────────────┘
#             non-capturing group

Çıktı şimdi ( ideone.com'da görüldüğü gibi ):

aaa 0
aaab 1 aaa|b        # (*gasp!*)
aaaxb 0
xaaab 0
b 0
abbb 1 a|b          # yes!
aabb 1 aa|bb        # YES!!
aaabbbbb 1 aaa|bbb  # YESS!!!
aaaaabbb 1 aaaaa|bb # NOOOOOoooooo....

Aha! Görünüşe göre şu anda çözüme gerçekten çok yaklaştık! Kendi kendine referans kullanarak grup 1'i "saymayı" başardık! Ama bekleyin ... İkinci ve son test durumlarında bir sorun var !! Yeterince bs yok ve bir şekilde yanlış sayıldı! Bir sonraki adımda bunun neden olduğunu inceleyeceğiz.

Ders : Kendine referans veren bir grubu "başlatmanın" bir yolu, kendi kendine referans eşleşmesini isteğe bağlı hale getirmektir.


Adım 4½: Neyin yanlış gittiğini anlamak

Sorun şu ki, öz referans eşleştirmeyi isteğe bağlı yaptığımız için, "sayaç", yeterli sayıda olmadığında "sıfırlanabilir" b. aaaaabbbGirdi olarak modelimizin her yinelemesinde neler olduğunu yakından inceleyelim .

 a a a a a b b b
↑
# Initial state: Group 1 is "uninitialized".
           _
 a a a a a b b b
  ↑
  # 1st iteration: Group 1 couldn't match \1 since it was "uninitialized",
  #                  so it matched and captured just b
           ___
 a a a a a b b b
    ↑
    # 2nd iteration: Group 1 matched \1b and captured bb
           _____
 a a a a a b b b
      ↑
      # 3rd iteration: Group 1 matched \1b and captured bbb
           _
 a a a a a b b b
        ↑
        # 4th iteration: Group 1 could still match \1, but not \1b,
        #  (!!!)           so it matched and captured just b
           ___
 a a a a a b b b
          ↑
          # 5th iteration: Group 1 matched \1b and captured bb
          #
          # No more a, + "loop" terminates

Aha! 4. yinelememizde hala eşleşebilirdik \1, ancak eşleşemedik \1b! Öz referans eşleştirmenin isteğe bağlı olmasına izin verdiğimizden \1?, motor geri adım atar ve "hayır, teşekkürler" seçeneğini aldı, bu da bizim eşleştirme ve tam olarak yakalamamıza olanak tanır b!

Bununla birlikte, ilk yineleme dışında, her zaman yalnızca öz referansla eşleşebileceğinizi unutmayın \1. Elbette bu açıktır, çünkü önceki yinelememizde yakaladığımız şeydir ve kurulumumuzda onu her zaman yeniden eşleştirebiliriz (örneğin bbb, en son yakaladıysak , hala olacağına dair garantimiz var bbb, ancak olabilir veya bbbbbu sefer olmayabilir ).

Ders : Geri izleme konusunda dikkatli olun. Düzenli ifade motoru, verilen kalıp eşleşene kadar izin verdiğiniz kadar geri izleme yapacaktır. Bu, performansı (yani yıkıcı geri izleme ) ve / veya doğruluğuetkileyebilir.


Adım 5: Kurtarma için kendi kendine sahip olma!

"Düzeltme" şimdi açık olmalıdır: isteğe bağlı tekrarlamayı iyelik nicelik belirteci ile birleştirin . Olduğunu, yerine basitçe ?, kullanım ?+yerine (örneğin, "işbirliği" tüm modelinin bir maç sonuçlanabilir bile, iyelik olarak ölçülür tekrarı sarfınazar değil unutmayın).

Gayri resmi terimlerle, bu ?+, ?ve ??şöyle diyor:

?+

  • (isteğe bağlı) "Orada olması gerekmez"
    • (iyelik) "ama eğer varsa, onu almalı ve bırakmamalısın!"

?

  • (isteğe bağlı) "Orada olması gerekmez"
    • (açgözlü) "ama eğer öyleyse, şimdilik alabilirsin,"
      • (geri izleme) "ancak daha sonra bırakmanız istenebilir!"

??

  • (isteğe bağlı) "Orada olması gerekmez"
    • (isteksiz) "ve öyle olsa bile, henüz almak zorunda değilsin,"
      • (geri izleme) "ancak daha sonra almanız istenebilir!"

Bizim kurulumunda, \1orada ilk defa olmayacak, ancak olacak hep orada bundan sonra herhangi bir zaman olabilir ve biz her zaman sonra eşleştirmek istiyoruz. Böylece \1?+tam olarak istediğimizi başarırdık.

$r5 = '/ ^ (?: a (?= a* (\1?+ b) ) )+ /x';
#          │     │      └──────┘ │ │
#          │     │          1    │ │
#          │     └───────────────┘ │
#          │         lookahead     │
#          └───────────────────────┘
#             non-capturing group

Şimdi çıktı ( ideone.com'da görüldüğü gibi ):

aaa 0
aaab 1 a|b          # Yay! Fixed!
aaaxb 0
xaaab 0
b 0
abbb 1 a|b
aabb 1 aa|bb
aaabbbbb 1 aaa|bbb
aaaaabbb 1 aaa|bbb  # Hurrahh!!!

Voilà !!! Sorun çözüldü!!! Şimdi doğru sayıyoruz, tam da istediğimiz gibi!

Ders : Açgözlü, isteksiz ve iyelik tekrarları arasındaki farkı öğrenin. İsteğe bağlı sahiplik, güçlü bir kombinasyon olabilir.


6. Adım: Rötuşları tamamlama

Yani şu anda sahip olduğumuz şey, atekrar tekrar eşleşen bir model ve eşleşen her abiri için b, grup 1'de yakalanan karşılık gelen bir örnek +var. Daha fazla aolmadığında veya iddia başarısız olduğunda sona erer , çünkü bir karşılık gelmez b. bir a.

İşi bitirmek için, bizim modelimize eklememiz yeterlidir \1 $. Bu, artık hangi grup 1'in eşleştiğine ve ardından hat bağlantısının sonuna bir geri referanstır. Çapa b, dizede fazladan 'lerin olmamasını sağlar ; başka bir deyişle, aslında bir n b n'ye sahibiz .

İşte 10.000 karakter uzunluğunda bir tane de dahil olmak üzere ek test senaryolarıyla birlikte son model:

$tests = array(
  'aaa', 'aaab', 'aaaxb', 'xaaab', 'b', 'abbb', 'aabb', 'aaabbbbb', 'aaaaabbb',
  '', 'ab', 'abb', 'aab', 'aaaabb', 'aaabbb', 'bbbaaa', 'ababab', 'abc',
  str_repeat('a', 5000).str_repeat('b', 5000)
);
 
$r6 = '/ ^ (?: a (?= a* (\1?+ b) ) )+ \1 $ /x';
#          │     │      └──────┘ │ │
#          │     │          1    │ │
#          │     └───────────────┘ │
#          │         lookahead     │
#          └───────────────────────┘
#             non-capturing group

: 4 adet eşleşmeleri bulur ab, aabb, aaabbbve bir 5000 b 5000 . O sürer sadece ideone.com çalıştırmak için 0.06s .


7. Adım: Java testi

Yani kalıp PHP'de çalışır, ancak nihai amaç Java'da çalışan bir kalıp yazmaktır.

public static void main(String[] args) {
 
        String aNbN = "(?x) (?:  a  (?= a* (\\1?+ b))  )+ \\1";
        String[] tests = {
                "",      // false
                "ab",    // true
                "abb",   // false
                "aab",   // false
                "aabb",  // true
                "abab",  // false
                "abc",   // false
                repeat('a', 5000) + repeat('b', 4999), // false
                repeat('a', 5000) + repeat('b', 5000), // true
                repeat('a', 5000) + repeat('b', 5001), // false
        };
        for (String test : tests) {
                System.out.printf("[%s]%n  %s%n%n", test, test.matches(aNbN));
        }
 
}
 
static String repeat(char ch, int n) {
        return new String(new char[n]).replace('\0', ch);
}

Model beklendiği gibi çalışıyor ( ideone.com'da görüldüğü gibi ).


Ve şimdi sonuca geliyoruz ...

Bu sözü gerektiğini a*lookahead ve gerçekten de "ana yılında +döngü", her iki izni geri dönüşlerle. Okuyucular, bunun neden doğruluk açısından bir sorun olmadığını ve neden aynı zamanda her ikisini birden sahiplenmenin de işe yarayacağını doğrulamaya teşvik edilir (belki de zorunlu ve zorunlu olmayan sahiplik belirleyiciyi aynı modelde karıştırmak yanlış algılamalara yol açabilir).

Ayrıca, a n b n ile eşleşecek bir düzenli ifade kalıbı olduğu düzgün olsa da , bunun pratikte her zaman "en iyi" çözüm olmadığı da söylenmelidir . Çok daha iyi bir çözüm, ^(a+)(b+)$hosting programlama dilinde grup 1 ve 2 tarafından yakalanan dizelerin uzunluğunu basitçe eşleştirmek ve ardından karşılaştırmaktır.

PHP'de şöyle görünebilir (ideone.com'da görüldüğü gibi ):

function is_anbn($s) {
   return (preg_match('/^(a+)(b+)$/', $s, $groups)) &&
      (strlen($groups[1]) == strlen($groups[2]));
}

Bu makalenin amacı, okuyucuları regex'in neredeyse her şeyi yapabileceğine ikna etmek DEĞİLDİR ; Açıkça olamaz ve yapabileceği şeyler için bile, daha basit bir çözüme yol açıyorsa, barındırma diline en azından kısmi yetkilendirme düşünülmelidir.

En üstte bahsedildiği gibi, bu makale zorunlu [regex]olarak stackoverflow için etiketlenmiş olsa da, belki de bundan daha fazlasıdır. İddialar, iç içe geçmiş referanslar, iyelik nicelik belirteci, vb. Hakkında öğrenmenin kesinlikle değeri olsa da, belki de buradaki daha büyük ders, bir kişinin sorunları çözmeye çalışabileceği yaratıcı süreç, maruz kaldığınızda genellikle gerektirdiği kararlılık ve sıkı çalışmadır. çeşitli kısıtlamalar, çalışan bir çözüm oluşturmak için çeşitli bölümlerden sistematik kompozisyon vb.


Bonus malzeme! PCRE özyinelemeli desen!

PHP'yi ortaya çıkardığımız için, PCRE'nin özyinelemeli kalıp ve alt yordamları desteklediği söylenmelidir. Bu nedenle, aşağıdaki kalıp preg_match( ideone.com'da görüldüğü gibi ) için çalışır :

$rRecursive = '/ ^ (a (?1)? b) $ /x';

Şu anda Java'nın normal ifadesi yinelemeli kalıbı desteklemiyor.


Daha da fazla bonus malzeme! Eşleşen bir n- b , n c n !!

Yani , normal olmayan, ancak yine de bağlamdan bağımsız olan a n b n'yi nasıl eşleştireceğimizi gördük , ancak bağlamdan bağımsız bile olmayan a n b n c n'yi de eşleştirebilir miyiz ?

Cevap elbette EVET! Okuyucuların bunu kendi başlarına çözmeye çalışmaları önerilir, ancak çözüm aşağıda sunulmuştur ( ideone.com'da Java'da uygulama ile ).

^ (?: a (?= a* (\1?+ b) b* (\2?+ c) ) )+ \1 \2 $


Şüphesiz bu uzun cevapta hatalar / yazım hataları olabilir, bu yüzden lütfen geri bildirimleri yorum olarak bırakın, böylece onları kendi başıma gözden geçirebilirim.
polygenelubricants

İyi iş. Okumam biraz zaman alacak, ancak son satırı okumak temelde imkansız; yazı tipi çok küçük. ------ Bekle. Bu bir featuremi? .... Bunun iyi bir fikir olup olmadığından emin değilim. Son sembolün ne olduğunu biliyorum, ancak okunamıyor (kopyalayıp yapıştırmanın dışında).
Peter Ajtai

6
@Peter: Küçük metni vurgulayın ve kopyalayıp başka bir şeye yapıştırın. Bilerek okumak zorlaştı: bu bir spoiler, bonus bulmacasının çözümü.
polygenelubricants

8
+1: Harika bir açıklama, bu "İleri düzey makaleler" harika fikirler.
Callum Rogers

1
@LarsH PHP's preg_match()bir PCRE örneğidir . Java regex'leri Perl regexps'in eski bir sürümüne dayanıyor gibi görünüyor . Bu, PHP regex'lerinin Java'daki sürümden daha güçlü olduğu anlamına gelir. 2013-02-21 itibariyle , pcre.txt yaklaşık olarak Perl 5.12'ye karşılık geldiğini belirtmektedir . Perl şu anda 5.16 iken, 5.18 birkaç ay kapalı. (Aslında o dönemde normal ifadelere pek bir şey eklenmedi)
Brad Gilbert

20

Özyinelemeli kalıpları destekleyen PCRE'den söz edilmediği için, söz konusu dili tanımlayan PCRE'nin en basit ve en etkili örneğini belirtmek isterim:

/^(a(?1)?b)$/

+1 wow, PCRE'nin özyinelemeli kalıbı desteklediğini bilmiyordum (hala öğreniyorum! Her gün!). Bu bilgileri içerecek şekilde makaleyi revize ettim. Yinelemeli kalıbın eşleşebileceğini sanmıyorum a^n b^n c^n.
poligenelubricants

Unutulmamalıdır ki bu seçenek daha basittir, ancak gönderilen cevap kadar iyi değildir - uzun dizelerde özyineleme taşar.
Kobi

@Kobi Bu sizin "iyi" tanımınıza bağlıdır. Örneğin, özyinelemeli çözüm diğerinden yaklaşık bir kat daha hızlıdır ( codepad.viper-7.com/CWgy7c ). Ve anlaşılması çok daha kolay. Özyinelemeli çözüm, hemen hemen dilbilgisinin bir normal ifadeye dönüştürülmesidir (aslında bunu dilbilgisi biçiminde yazabilirsiniz, işe yarayacaktır).
NikiC

1
@polygeniclubricants, bu kalıbı iki özyinelemeli kalıpla eşleştirebilirsiniz; biri as ve s'leri byakalamadan tüketmek için (ve yinelemeyle aynı miktarda olduğunu doğrular), ardından tüm a'ları açgözlülükle tüketen bir yakalama normal ifadesi izler ve ardından özyinelemeli aynı sayıda bs ve cs olduğunu doğrulamak için desen . Regex geçerli: /^(?=(a(?-1)?b)c)a+(b(?-1)?c)$/x. Kredi: nikic.github.io/2012/06/15/…
Josh Reback

11

Soruda belirtildiği gibi - .NET dengeleme grubu ile, a n b n c n d n … z n tipindeki modeller kolaylıkla eşleştirilebilir.

^
  (?<A>a)+
  (?<B-A>b)+  (?(A)(?!))
  (?<C-B>c)+  (?(B)(?!))
  ...
  (?<Z-Y>z)+  (?(Y)(?!))
$

Örneğin: http://www.ideone.com/usuOE


Düzenle:

Özyinelemeli örüntülü genelleştirilmiş dil için bir PCRE kalıbı da vardır, ancak bir önden okuma gereklidir. Bunun yukarıdakilerin doğrudan çevirisi olduğunu sanmıyorum.

^
  (?=(a(?-1)?b))  a+
  (?=(b(?-1)?c))  b+
  ...
  (?=(x(?-1)?y))  x+
     (y(?-1)?z)
$

Örneğin: http://www.ideone.com/9gUwF


1
@poly: Teşekkürler :). Aslında .NET kalıplarına aşina değilim, ancak bu tür kalıplar için dengeleme gruplarının çok kolay olduğu ortaya çıkıyor, bu yüzden bu yanıtı tamamlıyorum.
kennytm

bunu özyinelemeli desenle yapabilir misin? Çünkü yapamazsanız, bu, dengeleme grubunun yinelemeli modelin yapamadığı şeyleri yapabileceği ilginç bir bükülme. (Ve evet, eki çok takdir ediyorum).
poligenelubricants

Bu arada, .NET çözümünü atlamamın nedeni " a^n b^n.NET regex ile nasıl eşleşebiliriz ?" planlarım olmasıydı. Gelecekte bir makale, ancak isterseniz yazabilirsiniz. Bu makaleleri sadece kendim için yapmıyorum; Sitede iyi içeriğe sahip olmak için başkalarını da bunu yapmaya teşvik etmek istiyorum.
poligenelubricants

Bunu yinelemeli kalıplarla yapmanın bir yolunu bulursanız lütfen güncelleyin. Uzunlukları bir Fibonacci serisini oluşturan kelimeleri yakalamak için dengeleme gruplarıyla oynadım ve işe yaramadı. Yaptığım şeye benzer şekilde etrafa bakınarak mümkün olabilir.
Kobi

1
Bu kalıbın PCRE sürümünün, bir sonraki karakter yığını öncekinden daha uzunsa eşleştiği için biraz kusurlu olduğunu belirtmek isterim. Buraya bakın: regex101.com/r/sdlRTm/1 Sen ihtiyaç eklemek için (?!b), (?!c)şöyle yakalama gruplarına sonra, vb: regex101.com/r/sdlRTm/2
jaytea
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.