2010-03-07 44 views
10

açgözlü olmalı, tembel davranıyor, ancak aşağıdaki kodda değil:Regex Ben varsayılan olarak benim <strong>Regex</strong> istediğim açgözlü davranış gösteren düşündüm

Regex keywords = new Regex(@"in|int|into|internal|interface"); 
var targets = keywords.ToString().Split('|'); 
foreach (string t in targets) 
    { 
    Match match = keywords.Match(t); 
    Console.WriteLine("Matched {0,-9} with {1}", t, match.Value); 
    } 

Çıktı:

Matched in  with in 
Matched int  with in 
Matched into  with in 
Matched internal with in 
Matched interface with in 

Şimdi ben ben sadece uzunluk azalan anahtar kelimeleri sıralanmış eğer bu küçük örneğin işe ancak

    farkında olduğumuzdan o alfabetik sırayla onları tutmak önemlidir
  • Ben beklendiği gibi bu neden çalışmadığını anlamak istiyorum ve
  • Ben üzerinde çalışıyorum fiili proje Regex daha birçok kelime vardır ve .

Bu yüzden sorum şu: Bu neden tembel ve nasıl düzeltebilirim?

+0

Gerçek kullanımınızın daha karmaşık olup olmadığından emin değilim, ancak yukarıdaki örnek aslında yaptığınız şey ise, IndexOf yöntemi ile eşleşmeleri arayan sözcük listenizde döngüden bin kat daha iyi olacağını düşünüyorum . Regex, bir değişimde sadece bir grup kelime içeriyorsa, performans muhtemelen berbat olacaktır. – Josh

+0

@Josh - Hayır, örnek basitleştirildi. Gerçek uygulama lexers ve dilbilgisi ayrıştırıcıları oluşturmak için dil dosyalarını okuyor. Ben regex'imde biraz paslıyım; Benim sorunum şimdi çok açık görünüyor! – Stomp

+0

@Josh: Regex motorları, ortak bir önekle eşleşemedikten sonra birçok kontrolün atılması dahil olmak üzere, bu tür durumlar için birçok optimizasyon yapabilir. Örneğin, eğer ilk karakter "i" değilse, "i" ile başlayan dalların hiçbiri kontrol edilmeyecektir. .NET motorunun bunu yapıp yapmadığından emin değilim, ama yapmadıysa şaşırdım. –

cevap

12

Laziness ve oburluk sadece Nicelik (?, *, +, {min,max}) için de geçerlidir. Alternatifler her zaman sırayla eşleşir ve ilk olası eşleşmeyi deneyin.

+0

+1, açgözlülük için nicelleştirici olmalıdır. – codaddict

+0

Yeniden sipariş vermekten başka seçenek yok mu? Hrmmm ... Sanırım uçarak yeniden sipariş verebilirim, böylece tanımı alfabetik sırada tutabilirim ... – Stomp

+0

@Stomp: Evet, bu yapılabilir. Listeyi alfabetik olarak programda saklayın ve gerçekte uygulayabilmeniz için önce uzunluğa göre sıralayabilirsiniz. – codaddict

3

RegularExpressions.info'a göre, normal ifadeler eager'dir. Bu nedenle, piped expression'un içinden geçtiğinde, ilk katı eşleşmeyi durdurur.

Benim önerim, tüm anahtar kelimelerinizi bir dizide veya listede saklamak ve gerektiğinde sıralanmış, piped ifadesini oluşturmak olacaktır. Anahtar kelime listeniz değişmediği sürece bunu bir kez yapmanız gerekir. Oluşturulan ifadeyi tek bir sıralamada saklayın ve normal ifadeler üzerinde döndürün.

+0

@Jeras - Linkler için teşekkürler! MSDN'de arama yapıyordum ve ilk maçı merakla beklediğini unutmuş olmalıyım. – Stomp

6

Bir şeyleri kırmaya çalışmak gibi görünüyor. Bunu yapmak için tüm ifadenin doğru olması gerekiyor, mevcut olanı değil. .. Onun yerine bunu deneyin

new Regex(@"\b(in|int|into|internal|interface)\b"); 

"\ b", sözcük sınırları maç için diyor ve sıfır genişlikli bir eştir. Bu yerel bağımlı davranıştır, ancak genel olarak bu, boşluk ve noktalama işaretleri anlamına gelir. Sıfır genişlikli bir eşleşme olması, normal ifade motorunun sözcük sınırını algılamasına neden olan karakteri içermez.

+1

'\ b' eklenmesi istenen davranışı ortaya çıkarır, ancak nasıl çalıştığını karıştırırsınız. '\ b''^',' $ 've lookarounds gibi sıfır genişlikte bir onaylamadır; Bir karakteri eşleştirmek yerine, bir karakterden * önce veya sonra hayali boşluğu * eşler. İlk veya son karakter (sırasıyla) bir sözcük karakteri ise, bir dizenin başı veya sonu otomatik olarak bir sözcük sınırıdır, bu nedenle ikinci ifadeniz, ilkinin yalnızca daha ayrıntılı bir sürümüdür. –

+0

@Alan, Kodu çalıştırmayı denedim ve açıkça haklısınız. Orada ne yaptığımızı görmek için işyerindeki kodu kontrol etmem gerekecek ... Belki de \ W kullanıyoruz ve \ b değil. Bazı sıradan yakalama gruplarının kurulumunu yaptığımızı bildiğim benzer bir durumda "kelime olmayan" karakterler aldığımızı biliyorum. Yerel duyarlılığa gelince, sözcük sınırlarının noktalama işaretinin rolüne bağlı olarak farklı şekilde tanımlanacağı durum böyle olacaktır. –

+0

@Alan, geri bildiriminizi yansıtmak için cevabımı değiştirdim. –