Bir normal ifadede köşeli parantezler ile parantezler arasındaki fark nedir?


101

İşte JavaScript'te kullanmak için oluşturduğum normal bir ifade:

var reg_num = /^(7|8|9)\d{9}$/

Ekip üyem tarafından önerilen bir tane daha.

var reg_num = /^[7|8|9][\d]{9}$/

Kural, bir telefon numarasını doğrulamaktır:

  • Yalnızca on rakamdan oluşmalıdır.
  • İlk sayının 7, 8 veya 9'dan herhangi biri olması gerekiyor.

Yanıtlar:


124

Bu normal ifadeler eşdeğerdir (eşleştirme amaçları için):

  • /^(7|8|9)\d{9}$/
  • /^[789]\d{9}$/
  • /^[7-9]\d{9}$/

Açıklama:

  • (a|b|c)"OR" normal ifadesidir ve "a veya b veya c" anlamına gelir, ancak OR için gerekli olan parantezlerin varlığı da rakamı yakalar . Kesinlikle eşdeğer olmak için, kodlayacağınıza (?:7|8|9)bir hale getirmek için sigara yakalama grubudur.

  • [abc]"a, b veya c'den herhangi bir karakter" anlamına gelen bir "karakter sınıfı" dır (bir karakter sınıfı aralıklar kullanabilir, örneğin [a-d]= [abcd])

Bu normal ifadelerin benzer olmasının nedeni, bir karakter sınıfının "veya" için bir kısaltma olmasıdır (ancak yalnızca tek karakterler için). Bir alternatif olarak, (abc|def)bir karakter sınıfına çevrilemeyen bir şey de yapabilirsiniz .


30
(7|8|9)ve [789]eşdeğer değildir, çünkü ilki yakalar, ikincisi değildir. (?:7|8|9)öte yandan eşdeğer olacaktır (elbette bunu biliyorsunuz sanırım ...).
hochl

Bu regex görüyorum: [<<|>>|\]\]|\[\[]. Bağlam nedeniyle, normal ifadenin <<veya >>veya [[veya ile eşleşmeye çalıştığını biliyorum ]]. Ama söylediklerinize göre, <veya >veya [veya ile eşleşmeli ]. |Aralarında kullanırsanız [], parantezler farklı mı davranır?
Daniel Kaplan

1
@DanielKaplan , boru karakterinin kendisiyle eşleşmesini istemediğiniz sürece |bir karakter sınıfı içinde kullanmaz [...]. Ayrıca bir karakter sınıfındaki karakterleri çoğaltmanın bir etkisi yoktur - bir karakter sınıfı, karakterlerin bir listesidir ve tam olarak bunlardan biriyle eşleşir. Tahminimce normal yuvarlak parantez kullanan bir grup istiyorsunuz :(<<|>>|\]\]|\[\[)
Bohemian

57

Yapılan hata dışında ekibinizin tavsiyesi neredeyse doğrudur. Nedenini bulduğunuzda asla unutmayacaksınız. Bu hataya bir bakın.

/^(7|8|9)\d{9}$/

Bu ne yapar:

  • ^ve $bağlantılı eşleşmeleri belirtir, bu da bu çapalar arasındaki alt modelin tüm eşleşme olduğunu iddia eder. Dize, yalnızca bir bölümle değil, alt şablonun tamamıyla eşleşirse eşleşir.
  • ()bir yakalama grubunu belirtir .
  • 7|8|9ya eşleşen belirtmektedir 7, 8ya da 9. Bunu dönüşümlü olarak yapar , bu da boru operatörünün |yaptığı şeydir - dönüşümler arasında dönüşümlü olarak. Bu, dönüşümler arasında geriye doğru izler: İlk değişim eşleşmezse, motor, bir sonraki dönüşümle eşleşmeye devam etmek için, dönüşümün eşleşmesi sırasında işaretçi konumu hareket etmeden önce geri dönmelidir; Oysa karakter sınıfı sırayla ilerleyebilir. Optimizasyonların devre dışı bırakıldığı bir normal ifade motorunda bu eşleşmeyi görün:
Pattern: (r|f)at
Match string: carat

dönüşümler

Pattern: [rf]at
Match string: carat

sınıf

  • \d{9}dokuz basamakla eşleşir. \dherhangi bir rakamla eşleşen kısaltılmış bir meta karakterdir.
/^[7|8|9][\d]{9}$/

Ne yaptığına bakın:

  • ^ve $bağlantılı eşleşmeleri de gösterir.
  • [7|8|9]bir karakter sınıfıdır . Listeden herhangi bir karakter 7, |, 8, |, ya da 9bu şekilde, uyumlu olabilir |yanlış ilave edildi. Bu geri izleme olmadan eşleşir.
  • [\d]meta karakterde yer alan bir karakter sınıfıdır \d. Bu arada, bir karakter sınıfının ve tek bir meta karakterin kullanımının birleşimi kötü bir fikirdir, çünkü soyutlama katmanı eşleşmeyi yavaşlatabilir, ancak bu yalnızca bir uygulama ayrıntısıdır ve yalnızca birkaç normal ifade uygulaması için geçerlidir. JavaScript bir değildir, ancak alt şablonu biraz daha uzun hale getirir.
  • {9} önceki tek yapının toplamda dokuz kez tekrarlandığını gösterir.

Optimal normal ifade olduğu /^[789]\d{9}$/için, /^(7|8|9)\d{9}$/yakalar gereksiz en düzenli ifade uygulamaları ile ilgili bir performans düşüşü (getirir kisoru varkodda anahtar kelime kullandığını düşünürsek , bu muhtemelen JavaScript'tir). Kullanımıpreg eşleştirmesi için PCRE üzerinde çalışan, geri izleme eksikliğini ortadan kaldıracaktır, ancak biz de PHP'de değiliz, bu nedenle []alternatifler yerine sınıflar kullanmak |, maç geri dönmediğinden performans bonusu verir ve bu nedenle hem eşleşir hem de sizin kullanmaktan daha hızlı başarısız olur. önceki normal ifade.


6
sadece ilgimi çekiyor, bu ekran görüntüsü hangi programdan?
Mr Mystery Guest

12

İlk 2 örnek, onları bir şeyle DEĞİŞTİRİYORSANIZ çok farklı davranır. Bununla eşleşirseniz:

str = str.replace(/^(7|8|9)/ig,''); 

7 veya 8 veya 9'u boş dizeyle değiştirirsiniz.

Eğer bununla eşleşirsen

str = str.replace(/^[7|8|9]/ig,''); 

Eğer yerini alacak 7ya 8ya 9VEYA Dikey Bar !!!! boş dizeye göre.

Bunu zor yoldan öğrendim.


6
SO'ya hoş geldiniz! Değiştirme veya eşleştirme, tamamen yanlış. Pek çok insan bu hatayı yapar ve genellikle bundan sıyrılır - yıllarca, bazen - çünkü giriş dizgeleri hiçbir zaman bir boru ( |) içermez .
Alan Moore
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.