[01-12] aralığı neden beklendiği gibi çalışmıyor?


94

[01-12]Normal ifadede aralık kalıbını iki basamaklı mm ile eşleşecek şekilde kullanmaya çalışıyorum , ancak bu beklendiği gibi çalışmıyor.


9
Sen eşleşen ediyoruz karakterleri , değil karakter dizileri . Temel olarak, 0, 1 ila 1 ve 2 (yani, 0, 1 ve 2) ile eşleşiyorsunuz. Şunu düşünün: Bu [a-z0-9], tüm küçük harflerle ve tüm rakamlarla eşleşir, ancak yalnızca tek bir karakter olarak.
Lasse V.Karlsen

fwiw İki girişten (min / maks.) son derece optimize edilmiş bir normal ifade oluşturan bir javascript aracı oluşturdum github.com/jonschlinkert/to-regex-range
jonschlinkert

0 [1-9] | 1 [0-2] -> 0 | 1 | 2 -> [] düzenli ifadeler bir karakter sınıfını belirtir. Aralık belirtilmezse, örtük olarak her karakteri veya her karakteri belirtir.
Badri Gs

Saf normal ifadeyle eşleştirmeniz gerekiyor mu? Değilse, şunları yapabilirsiniz: 1.) sadece \d+kalıbı kullanın , 2.) eşleşen dizeleri kodunuzdaki sayılara dönüştürün. ve sonra, 3.) gibi sayı aralığını kontrol edin if(num >= 0 && num <= 12){ /*do something*/ }. Çok daha hızlı ve esnek.
2018, 17:47

Yanıtlar:


204

Normal ifadede karakter sınıfları tanımının nasıl çalıştığını yanlış anlamış görünüyorsunuz.

Dizeleri herhangi eşleştirmek için 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, veya 12, bu eserlerin gibi bir şey:

0[1-9]|1[0-2]

Referanslar


Açıklama

Bir karakter sınıfı, kendi başına, girdi dizesinden bir ve tam olarak bir karakterle eşleşmeye çalışır . [01-12]aslında tanımlar [012], 3 karakterlerden herhangi karşı girişten bir karakter eşleşen bir karakter sınıfını 0, 1ya 2.

-Aralık tanımı gider 1için 1sadece içeren, 1. Öte yandan, bir şey gibi [1-9]içerir 1, 2, 3, 4, 5, 6, 7, 8, 9.

Yeni başlayanlar genellikle benzer şeyleri tanımlarken hata yaparlar [this|that]. Bu "işe yaramıyor". Bu karakter tanımı tanımlar [this|a], bu 6 karakter herhangi birine karşı giriş bir karakter ile eşleşir, yani t, h, i, s, |ya da a. Muhtemelen (this|that)amaçlanan şeydir.

Referanslar


Aralıklar nasıl tanımlanır

Bu yüzden artık böyle bir modelin between [24-48] hours"işe yaramadığı" açık. Bu durumda karakter sınıfı eşdeğerdir [248].

Yani, -bir karakter sınıfı tanımında, modeldeki sayısal aralığı tanımlamaz. Normal ifade motorları, sonlu tekrar sözdizimi dışında (ör . a{3,5}3 ile 5 arasındaki eşleşmeler a) kalıptaki sayıları gerçekten "anlamaz" .

Aralık tanımı, aralıkları tanımlamak için karakterlerin ASCII / Unicode kodlamasını kullanır. Karakter 0ASCII'de 48 ondalık olarak kodlanmıştır; 957'dir. Dolayısıyla, karakter tanımı [0-9], kodlamada değerleri ondalık 48 ile 57 arasında olan tüm karakterleri içerir. Aksine makul, tasarım olarak bu karakterler 0, 1, ..., 9.

Ayrıca bakınız


Başka bir örnek: A'dan Z'ye

Başka bir ortak karakter sınıfı tanımına bir göz atalım [a-zA-Z]

ASCII'de:

  • A= 65, Z= 90
  • a= 97, z= 122

Bu şu demek:

  • [a-zA-Z]ve [A-Za-z]eşdeğerdir
  • Çoğu tatta, [a-Z]muhtemelen geçersiz bir karakter aralığıdır
    • çünkü a(97), Z(90) ' dan "büyüktür"
  • [A-z] yasaldır, ancak şu altı karakteri de içerir:
    • [(91), \(92), ](93), ^(94), _(95), `(96)

İlgili sorular


Benim için, tek basamaklıysa 0 ile ön ek olmadan aylar arıyordum. Ve bunu kullandım ([1-9] | (1 [0-2])) ve işe yarıyor.
bunjeeb

3
Unutulmaması gereken önemli: Bu sayfayı, onlarca ulaşmadan önce yalnızca tek basamaklı sayı aralığınız için bir çözüm arayan bulursanız, 0[1-9]|1[0-2]çalışmayacaktır. Mantıksal bir sonraki adıma bunu değiştirme [1-9]|1[0-2]anlaşılabilir nedenlerle (Uyuşuyor için ya çalışmıyor 1sadece 10, 11ve 12). \b(?:[0-9]|1[0-1])\bBunu önlemek için kullanmak zorunda kaldım . \bs, normal ifadenin kelime (veya bu durumda sayı) sınırlarıyla eşleştiğinden ( ^& $yoktu) emin olur; parantezler veya ( |) diğer tarafını dikkate alır; ve son ?:olarak, parantez kullanımıyla bir alt eşleşme oluşturmamaktır.
user66001

@polygenelubricants: "1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )Lütfen bu JS normal ifadesinin neden 17'nin üzerinde eşleştiğini söyleyebilir misiniz?
edam

@edam - polygenelubricants ve bu yüzden, ama sonra olurdu olabilir olabilir yanıtlayan bir questi ... beklemek ... Bu bir olduğunu soru bir de soruyorsun yorumun ? Orada rulez bu sitede;) Eğer yeni bir soru varsa Soru Sor. Yorumlar sadece eleştiri ve açıklama istemek ve bunlara cevap vermek içindir.
robinCTS

1
@edam Oh, görüyorum. Sen mi bir saat sonra bir soru olarak-re istiyoruz. Bu harika! Ancak, yorumunuzu buradan silmek muhtemelen iyi bir fikir olacaktır.
robinCTS

24

Normal ifadelerdeki [...]sözdizimi ile gösterilen bir karakter sınıfı , girdideki tek bir karakterle eşleşecek kuralları belirtir . Bu nedenle, köşeli parantezler arasında yazdığınız her şey tek bir karakterin nasıl eşleştirileceğini belirtir .

Böylece kalıbınız [01-12]şu şekilde ayrıştırılır:

  • 0 - tek rakamla eşleşir 0
  • veya 1-1, 1 ile 1 arasındaki tek bir rakamla eşleşir
  • veya 2, tek basamaklı 2 ile eşleşir

Yani temelde tek eşleştirdiğiniz 0, 1 veya 2.

01-12 arasında değişen iki haneyi eşleştirerek istediğiniz eşleştirmeyi yapabilmek için metin olarak nasıl görüneceklerini düşünmeniz gerekir.

Var:

  • 01-09 (ör. İlk hane 0, ikinci hane 1-9)
  • 10-12 (ör. İlk hane 1, ikinci hane 0-2)

Daha sonra bunun için aşağıdaki gibi görünebilen bir düzenli ifade yazmanız gerekecek:

  +-- a 0 followed by 1-9
  |
  |      +-- a 1 followed by 0-2
  |      |
<-+--> <-+-->
0[1-9]|1[0-2]
      ^
      |
      +-- vertical bar, this roughly means "OR" in this context

Daha kısa bir ifade elde etmek için bunları birleştirmeye çalışmanın, geçersiz giriş için yanlış pozitif eşleşmeler vererek başarısız olacağını unutmayın.

Örneğin, kalıp [0-1][0-9]temelde istediğinizden biraz daha fazla olan 00-19 sayılarıyla eşleşir.

Karakter sınıfları hakkında daha fazla bilgi için kesin bir kaynak bulmaya çalıştım, ancak şimdilik size verebileceğim tek şey bu Regex Karakter Sınıfları için Google Sorgusu . Umarım orada size yardımcı olacak daha fazla bilgi bulursunuz.


9

Bu aynı zamanda çalışır:

^([1-9]|[0-1][0-2])$

[1-9] 1 ile 9 arasındaki tek rakamlarla eşleşir

[0-1][0-2] 10 ile 12 arasındaki çift rakamlarla eşleşir

Burada bazı iyi örnekler var


2
Tam olarak [0-1][0-2]eşleşir 00. Bununla birlikte, bağlantı için +1 (cevabımda kullandım) dedi.
poligenel yağlayıcılar

2
[0-1][0-2]o dizeleri gibi verdiğinden dikkatli yorumlanması gerekir 00, 01ve 02, ama kabul etmez 03kadar 09, nihayet itiraf 10, 11ve 12. Bunun için doğru bir normal ifade [1-9]|1[0-2], veya hatta 0*([1-9]|1[0-2])(bu sonuncu herhangi bir sayıda önde gelen sıfırlara izin verir).
Luis Colorado

1

[]Bir anlamında olabildikleri bir regex s karakter sınıfı . Aralık belirtilmezse, örtük olarak veya içindeki her karakter birlikte olur. Böylece, [abcde]aynı (a|b|c|d|e)bir şey yakalamak etmemesi dışında; o birini maç olacak a, b, c, d, veya e. Bir aralığın tümü bir karakter kümesidir ; [ac-eg]diyor "şunlardan herhangi biriyle eşleş a:; cve arasındaki herhangi bir karakter eveya g". Böylece, eşleşmeniz "şunlardan herhangi biriyle eşleşir 0:; 1ve arasındaki herhangi bir karakter 1( yani , sadece 1); veya 2.

Amacınız belli ki bir sayı aralığı belirlemektir: aradaki herhangi bir sayı 01ve 12iki basamakla yazılmış. Bu özel durumda, onu eşleşebilir 0[1-9]|1[0-2]: ya bir 0herhangi arasındaki rakam ile devam eden 1ve 9ya bir 1arasında herhangi rakam ile devam eden 0ve 2. Genel olarak, herhangi bir sayı aralığını benzer bir şekilde geçerli bir normal ifadeye dönüştürebilirsiniz. Normal ifadelerden daha iyi bir seçenek veya sizin için normal ifadeyi oluşturabilecek mevcut bir işlev veya modül olabilir. Dilinize bağlıdır.


0

Poligenel yağlayıcıların dediği gibi, karakter sınıfları ([] içindeki şeyler) dizelerden ziyade karakterlerle eşleştiği için, sizinki istediğiniz şey yerine 0 | 1-1 | 2 arayacaktır.


3
0|1-1|2- bu gösterim çok yanıltıcıdır. Böyle bir şey 0|1|2daha doğru olur.
poligenel yağlayıcılar

0

Bunu kullan:

0?[1-9]|1[012]
  • 07: geçerli
  • 7: geçerli
  • 0: eşleşmiyor
  • 00: eşleşmiyor
  • 13: eşleşmiyor
  • 21: eşleşmiyor

07/2018 olarak bir kalıbı test etmek için şunu kullanın:

/^(0?[1-9]|1[012])\/([2-9][0-9]{3})$/

(01/2000 - 12/9999 tarih aralığı)


Bunu nasıl yapacağımı anlamaya çalışıyordum ama sadece 0'ın üçüncü koşulunu geçmek için.
mkaatman
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.