Tam olarak n OR m kez normal ifade


105

Şu normal ifadeyi düşünün Xolan herhangi regex.

X{n}|X{m}

Bu normal ifade, tam olarak veya kez Xoluşup oluşmadığını test eder . nm

Bir oluşumu Xtam olarak nveya mkez test edebilen bir normal ifade nicelik belirteci var mı ?


Oluşumları sayılı İki Xgenel için alabilirsiniz en iyisi m, n.
John Dvorak

Bu benim sorunum olsaydı, normal ifade geri referanslarını denerdim ve başlayacaktım (X)\1{n-1}(?:\1{m-n-1}). Bunun Xen az bir kez eşleştiğini biliyorum , ancak sadece başlamak için bu basit şeyi deneyin, ardından bunun yerine önden veya arkaya bakmayı kullanarak hassaslaştırın (X).
nalply

Yanıtlar:


91

"Tam olarak m veya n kez" anlamına gelen tek bir nicelik belirteci yoktur. Yapma şeklin iyi.

Bir alternatif şudur:

X{m}(X{k})?

nerede m < nve kdeğeridir n-m.


67

Nicelik belirteçlerinin tam listesi (ref. Http://www.regular-expressions.info/reference.html ):

  • ?, ??- 0 veya 1 oluşum ( ??tembel, ?açgözlü)
  • *, *?- herhangi bir sayıda oluşum
  • +, +?- en az bir kez
  • {n}- tam olarak noluşumlar
  • {n,m}- niçin mbulunuşu, kapsayıcı
  • {n,m}?- niçin mbulunuşu, tembel
  • {n,}, {n,}?- en azından noluşum

"Tam olarak N veya M" elde etmek için, ölçülen normal ifadeyi iki kez yazmanız gerekir, m, n özel değilse:

  • X{n,m} Eğer m = n+1
  • (?:X{n}){1,2} Eğer m = 2n
  • ...

1
?:If m = 2nörneğinde neden gerekli ? Benim için onsuz iyi çalışıyor gibi görünüyor.
erb

7
@erb dışarıda kalırsanız ?:, grup bir yakalama grubu haline gelir. Düzenli ifade motorunun gerekmeyen şeyleri hatırlamasının yanı sıra, bundan sonra grupları yakaladıysanız, kimlikleri değişecektir. Normal ifadenizi değiştirme için kullanırsanız, değiştirmeyi ayarlamanız gerekir.
John Dvorak


3

TLDR; (?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

İstediğiniz gibi görünüyor "xn kez" veya "xm kere" Ben regex bir edebi çeviri olacağını düşünüyorum (x{n}|x{m}). Bunun gibi https://regex101.com/r/vH7yL5/1

veya m "x" s'den daha büyük bir diziye sahip olabileceğiniz bir durumda (m> n varsayılırsa), "x" olmadan "x" ve ardından "x" yok, çeviri yaparak ekleyebilirsiniz, [^x](x{n}|x{m})[^x]ancak bu "x" lerin arkasında ve arkasında her zaman bir karakter olduğunu varsayın. Burada görebileceğiniz gibi: https://regex101.com/r/bB2vH2/1

Eğer bunu değiştirebilir (?:[^x]|^)(x{n}|x{m})(?:[^x]|$)"hayır 'x' veya satır sonuna kadar takip ardından" " 'x' hayır şu veya satır başlangıç aşağıdaki" ve tercüme. Ancak yine de, burada görebileceğiniz gibi, aralarında yalnızca bir karakter bulunan iki diziyi eşleştirmeyecektir (çünkü ilk eşleşme sonrasında bir karakter ve ikincisi daha önce bir karakter gerektirecektir): https://regex101.com/r/ oC5oJ4 / 1

Son olarak, bir karakterlik uzak eşleşmeyi eşleştirmek için, "sonra 'x' yok" üzerine olumlu bir ön bakış (? =) Veya "önce 'x' yok" üzerine olumlu bir bakış (? <=) Ekleyebilirsiniz, şunun gibi: https://regex101.com/r/mC4uX3/1

(?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

Bu şekilde, yalnızca istediğiniz 'x'lerin tam sayısını eşleştireceksiniz.


1

Enhardened'ın cevabına bir göz atarak, sondan bir önceki ifadelerinin aralarında yalnızca bir karakter bulunan dizilerle eşleşmeyeceğini belirtiyorlar. İleriye bakma / arkaya bakma özelliğini kullanmadan bunu düzeltmenin kolay bir yolu var ve bu başlangıç ​​/ bitiş karakterini sınır karakteriyle değiştirmektir. Bu, başlangıç ​​/ bitiş dahil olmak üzere kelime sınırlarıyla eşleşmenizi sağlar. Bu nedenle, uygun ifade şöyle olmalıdır:

(?:[^x]|\b)(x{n}|x{m})(?:[^x]|\b)

Burada görebileceğiniz gibi: https://regex101.com/r/oC5oJ4/2 .


1
Harika, regex'in sınırları nasıl işlediğine aşina değildim. Bu yöntemle ilgili tek sorun, standart olmayan bir sınır kullandığınız zamandır. Bir bakışın öyküsü : regex101.com/r/j0nkeo/1 ve regex101.com/r/4Ix7Dr/1
19'da

1
@Enhardened - bu iyi bir nokta, örtüşen birden fazla eşleşen grupla ilgili bir sorun gibi görünüyor. Bu, arkaya bak kullanmanız gereken bir durumdur.
rozza2058

1

Çok eski bir gönderi, ancak yardımcı olabilecek bir şeyle katkıda bulunmak istiyorum. Bunu tam olarak soruda belirtilen şekilde denedim ve işe yarıyor ama bir sorun var: Miktarların sırası önemlidir. Bunu düşün:

#[a-f0-9]{6}|#[a-f0-9]{3}

Bu, tüm onaltılık renk kodlarını bulacaktır (bunlar ya 3 ya da 6 basamak uzunluğundadır). Ama bunu böyle çevirdiğimde

#[a-f0-9]{3}|#[a-f0-9]{6}

sadece 3 rakamlı olanları veya 6 haneli olanların ilk 3 rakamını bulacaktır. Bu mantıklı ve bir Regex uzmanı bunu hemen fark edebilir, ancak çoğu kişi için bu tuhaf bir davranış olabilir. Sırası ne olursa olsun bu tuzağı engelleyebilecek bazı gelişmiş Regex özellikleri vardır, ancak herkes Regex kalıplarına diz boyu hakim değildir.

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.