TL; DR
Kullanım [.]
yerine \.
ve [0-9]
yerine \d
(Java gibi) bazı dillerde sorunları kaçan önlemek için.
Bunu başlangıçta tanıdığı için isimsiz olana teşekkürler .
Bir kayan nokta numarasını eşleştirmek için nispeten basit bir model ,
[+-]?([0-9]*[.])?[0-9]+
Bu eşleşecek:
Çalışan bir örneğe bakın
Ayrıca eşleştirme istiyorsanız 123.
(ondalık kısmı olmayan bir nokta), biraz daha uzun bir ifadeye ihtiyacınız olacak:
[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)
Bu modelin daha kapsamlı bir açıklaması için pkeller'in cevabına bakın
Onaltılık ve sekizlik gibi ondalık olmayan sayıları eklemek istiyorsanız, bir dizenin sayı olup olmadığını nasıl anlarım? .
Bir girişin bir sayı olduğunu doğrulamak istiyorsanız (giriş içinde bir sayı bulmak yerine), o zaman kalıbı ^
ve ile şöyle çevrelemelisiniz $
:
^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$
Düzensiz Normal İfadeler
Çoğu modern dilde, API'lerde, çerçevelerde, kitaplıklarda vb. Uygulanan "düzenli ifadeler", biçimsel dil teorisinde geliştirilen bir kavrama dayanmaktadır . Ancak, yazılım mühendisleri bu uygulamaları resmi tanımın çok ötesine taşıyan birçok uzantı eklediler. Dolayısıyla, çoğu düzenli ifade motoru birbirine benzese de, aslında bir standart yoktur. Bu nedenle, birçok şey kullandığınız dil, API, çerçeve veya kitaplığa bağlıdır.
(Bu arada, kafa karışıklığını azaltmaya yardımcı olmak için, birçok kişi bu gelişmiş eşleşen dilleri tanımlamak için " regex " veya " regexp " kullanmayı tercih etti. Daha fazla bilgi için RexEgg.com'da Normal İfade Normal İfade ile Aynı mı? Konusuna bakın.)
Bununla birlikte, çoğu normal ifade motoru (aslında, bildiğim kadarıyla hepsi) kabul ederdi \.
. Büyük olasılıkla, kaçışla ilgili bir sorun var.
Kaçmanın Sıkıntısı
JavaScript gibi bazı dillerde normal ifadeler için yerleşik destek bulunur . Yapmayan diller için kaçış bir sorun olabilir.
Bunun nedeni, temelde bir dilde bir dilde kodlama yapıyor olmanızdır. Örneğin Java, \
dizelerinde bir kaçış karakteri olarak kullanır , bu nedenle bir dizgeye değişmez bir ters eğik çizgi karakteri yerleştirmek istiyorsanız, ondan kaçmanız gerekir:
// creates a single character string: "\"
String x = "\\";
Bununla birlikte, normal ifadeler kaçış için karakteri de kullanır; \
bu nedenle, bir değişmez \
karakterle eşleştirmek istiyorsanız , normal ifade motoru için ondan kaçmalı ve ardından Java için tekrar çıkış yapmalısınız:
// Creates a two-character string: "\\"
// When used as a regex pattern, will match a single character: "\"
String regexPattern = "\\\\";
Sizin durumunuzda, muhtemelen programlama yaptığınız dilde ters eğik çizgi karakterinden kaçmadınız:
// will most likely result in an "Illegal escape character" error
String wrongPattern = "\.";
// will result in the string "\."
String correctPattern = "\\.";
Tüm bu kaçışlar çok kafa karıştırıcı olabilir. Çalıştığınız dil ham dizeleri destekliyorsa , ters eğik çizgi sayısını azaltmak için bunları kullanmalısınız, ancak tüm diller bunu yapmaz (en önemlisi: Java). Neyse ki, bazen işe yarayacak bir alternatif var:
String correctPattern = "[.]";
Bir normal ifade motoru için \.
ve [.]
tamamen aynı anlama gelir. Bunun yeni satır ( \\n
), açık köşeli parantez ( \\[
) ve ters eğik çizgi ( \\\\
veya [\\]
) gibi her durumda işe yaramayacağını unutmayın .
Eşleşen Numaralar Hakkında Bir Not
(İpucu: Düşündüğünüzden daha zor)
Bir sayıyı eşleştirmek, normal ifadeyle oldukça kolay olduğunu düşündüğünüz şeylerden biridir, ancak aslında oldukça zordur. Yaklaşımınıza parça parça bir göz atalım:
[-+]?
İsteğe bağlı bir -
veya+
[0-9]*
0 veya daha fazla ardışık basamağı eşleştir
\.?
İsteğe bağlı bir eşleştir .
[0-9]*
0 veya daha fazla ardışık basamağı eşleştir
İlk olarak, rakamlar için bir karakter sınıfı kısaltması kullanarak bu ifadeyi biraz temizleyebiliriz (bunun ayrıca yukarıda bahsedilen kaçış sorununa da açık olduğunu unutmayın):
[0-9]
= \d
\d
Aşağıda kullanacağım , ancak bununla aynı anlama geldiğini unutmayın [0-9]
. (Aslında, bazı motorlarda \d
tüm komut dosyalarındaki rakamlarla eşleşecek, bu yüzden istenenden daha fazla eşleşecek [0-9]
, ancak bu muhtemelen sizin durumunuzda önemli değil.)
Şimdi, buna dikkatlice bakarsanız, kalıbınızın her bir parçasının isteğe bağlı olduğunu fark edeceksiniz . Bu desen, 0 uzunluklu bir dizeyle eşleşebilir; yalnızca +
veya içeren bir dize -
; veya yalnızca a'dan oluşan bir dize .
. Muhtemelen amaçladığınız şey bu değil.
Bunu düzeltmek için, normal ifadenizi gerekli minimum dizeyle, muhtemelen tek bir rakamla "sabitleyerek" başlamak yararlıdır:
\d+
Şimdi ondalık kısmı eklemek istiyoruz, ancak düşündüğünüz yere gitmiyor:
\d+\.?\d* /* This isn't quite correct. */
Bu, gibi değerlerle eşleşmeye devam edecek 123.
. Daha da kötüsü, bunda bir miktar kötülük var. Nokta isteğe bağlıdır, yani yan yana ( \d+
ve \d*
) tekrarlanan iki sınıfınız vardır . Bu aslında yanlış bir şekilde kullanılırsa tehlikeli olabilir ve sisteminizi DoS saldırılarına açık hale getirir.
Bunu düzeltmek için, noktayı isteğe bağlı olarak ele almak yerine, gerektiği gibi ele almalıyız (tekrarlanan karakter sınıflarını ayırmak için) ve bunun yerine tüm ondalık kısmı isteğe bağlı yapmalıyız:
\d+(\.\d+)? /* Better. But... */
Bu şimdi daha iyi görünüyor. İlk basamak dizisi ile ikincisi arasında bir süreye ihtiyacımız var, ancak ölümcül bir kusur var: eşleşemiyoruz .123
çünkü artık bir ön basamak gerekli.
Bunu düzeltmek aslında oldukça kolaydır. Sayının "ondalık" kısmını isteğe bağlı yapmak yerine, ona bir karakter dizisi olarak bakmalıyız: 1 veya daha fazla sayı, .
önüne 0 veya daha fazla sayı eklenebilen bir ön ek olabilir:
(\d*\.)?\d+
Şimdi sadece işareti ekliyoruz:
[+-]?(\d*\.)?\d+
Elbette, bu eğik çizgiler Java'da oldukça can sıkıcıdır, bu nedenle uzun biçimli karakter sınıflarımızda bunların yerini alabiliriz:
[+-]?([0-9]*[.])?[0-9]+
Eşleştirme ve Doğrulama
Bu, yorumlarda birkaç kez gündeme geldi, bu yüzden eşleştirme ve doğrulama konusunda bir ek ekliyorum.
Eşleştirmenin amacı , girdi içindeki bazı içerikleri bulmaktır ("samanlıkta iğne"). Doğrulamanın amacı , girdinin beklenen bir formatta olmasını sağlamaktır.
Normal ifadeler, doğaları gereği yalnızca metinle eşleşir . Bazı girdiler verildiğinde, ya eşleşen bir metin bulacaklar ya da bulamayacaklar. Bununla birlikte, bir ifadeyi girişin başına ve sonuna tutturma etiketleriyle ( ^
ve $
) "yapıştırarak", girişin tamamı ifadeyle eşleşmedikçe hiçbir eşleşme bulunmamasını sağlayabilir ve bu da doğrulamak için düzenli ifadeleri etkili bir şekilde kullanabiliriz .
Yukarıda ( [+-]?([0-9]*[.])?[0-9]+
) açıklanan normal ifade, bir hedef dizedeki bir veya daha fazla sayıyla eşleşir . Yani girdi verildiğinde:
apple 1.34 pear 7.98 version 1.2.3.4
Regex maç olacak 1.34
, 7.98
, 1.2
, .3
ve .4
.
Verilen bir girdinin bir sayı olduğunu ve sayıdan başka bir şey olmadığını doğrulamak için, bağlantı etiketlerine sararak ifadeyi girdinin başına ve sonuna "yapıştırın":
^[+-]?([0-9]*[.])?[0-9]+$
Bu, yalnızca girişin tamamı bir kayan noktalı sayı ise bir eşleşme bulur ve giriş ek karakterler içeriyorsa bir eşleşme bulmaz. Dolayısıyla, girdi verildiğinde 1.2
, bir eşleşme bulunacak, ancak apple 1.2 pear
hiçbir eşleşme bulunmayacaktır.
Bazı regex motorlar olması Not validate
, isMatch
esasen ben dönmeden, otomatik tarif ettik yapar ki, ya da benzer işlevi true
bir eşleşme bulunursa ve false
eşleşme bulunursa. Ayrıca bazı motorların , tüm girdinin başlangıcı / bitişi yerine bir satırın başlangıcını / sonunu eşleştiren ^
ve tanımını değiştiren bayraklar ayarlamanıza izin verdiğini unutmayın $
. Bu genellikle varsayılan değildir, ancak bu bayraklara dikkat edin.