Geçenlerde yayınlanan bir cevap için R dili İngiltere posta kodları bu soruya . İngiltere Hükümeti'nin normal ifade modelinin yanlış olduğunu ve bazı posta kodlarını doğru bir şekilde doğrulayamadığını keşfettim . Ne yazık ki, buradaki cevapların çoğu bu yanlış kalıba dayanmaktadır.
Bu sorunlardan bazılarını aşağıda özetleyeceğim ve gerçekten işe yarayan düzeltilmiş düzenli bir ifade sunacağım .
Not
Cevabım (ve genel olarak düzenli ifadeler):
- Yalnızca posta kodu biçimlerini doğrular .
- Bir posta kodunun yasal olarak bulunmasını sağlamaz .
- Bunun için uygun bir API kullanın! Daha fazla bilgi için Ben'in cevabına bakınız .
Kötü normal ifade ile ilgilenmiyorsanız ve sadece cevaba atlamak istiyorsanız, Cevap bölümüne ilerleyin .
Kötü Düzenleme
Bu bölümdeki normal ifadeler kullanılmamalıdır.
Bu, İngiltere hükümetinin geliştiricilere sağladığı başarısız regex'tir (bu bağlantının ne kadar süreceğini bilmiyorum, ancak Toplu Veri Aktarımı belgelerinde görebilirsiniz ):
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$
sorunlar
Sorun 1 - Kopyala / Yapıştır
Kullanımdaki normal ifadeye bakın .
Birçok geliştiricinin yaptığı gibi, kodu kopyalar / yapıştırırlar (özellikle normal ifadeler) ve çalışmasını beklerken yapıştırırlar. Teoride bu harika olsa da, bu özel durumda başarısız olur, çünkü bu belgeden kopyala / yapıştır, aslında karakterlerden birini (boşluk) aşağıda gösterildiği gibi yeni satır karakterine dönüştürür:
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))
[0-9][A-Za-z]{2})$
Çoğu geliştiricinin yapacağı ilk şey, yeni satırı iki kez düşünmeden silmek. Şimdi normal ifade, posta kodlarını içindeki boşluklarla ( GIR 0AA
posta kodu dışında) eşleştirmeyecektir .
Bu sorunu gidermek için, yeni satır karakteri boşluk karakteriyle değiştirilmelidir:
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
^
Problem 2 - Sınırlar
Kullanımdaki normal ifadeye bakın .
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
^^ ^ ^ ^^
Posta kodu normal ifadesi normal ifadeyi yanlış bir şekilde sabitler. Posta kodlarını doğrulamak için bu normal ifadeyi kullanan herkes, böyle bir değer geçerse şaşırtabilir fooA11 1AA
. Bunun nedeni, yukarıdaki seçeneğin de işaret ettiği gibi, ilk seçeneğin başlangıcını ve ikinci seçeneğin sonunu (birbirinden bağımsız olarak) demirlemiş olmalarıdır.
Bunun anlamı, ^
(satırın başlangıcındaki konumu belirtir ) yalnızca ilk seçenek üzerinde çalışır ([Gg][Ii][Rr] 0[Aa]{2})
, bu nedenle ikinci seçenek posta koduyla biten tüm dizeleri doğrular (daha önce ne olursa olsun).
Benzer şekilde, ilk seçenek satırın sonuna kadar demirlemiş değildir $
bu yüzden, GIR 0AAfoo
aynı zamanda kabul edilir.
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$
Bu sorunu gidermek için, her iki seçeneğin de başka bir gruba (veya yakalamayan gruba) sarılması ve bunun etrafına tutturulması gerekir:
^(([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2}))$
^^ ^^
Sorun 3 - Uygunsuz Karakter Kümesi
Kullanımdaki normal ifadeye bakın .
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
^^
Normal ifade, -
bir dizi karakteri belirtmek için burada eksik . Durduğu gibi, bir posta kodu biçimindedir ANA NAA
(burada A
bir harfi N
temsil eder ve bir sayıyı temsil eder) ve A
veya dışında bir şeyle başlarsa Z
başarısız olur.
Bunun anlamı o maç olacak A1A 1AA
ve Z1A 1AA
ancak B1A 1AA
.
Bu sorunu gidermek için, karakter ilgili karakter kümesine ve -
arasına yerleştirilmelidir :A
Z
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
^
Sorun 4 - Yanlış İsteğe Bağlı Karakter Seti
Kullanımdaki normal ifadeye bakın .
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
^
Yemin ederim ki bu şeyi internette yayınlamadan önce test etmediler bile. Yanlış karakter setini isteğe bağlı yaptılar. [0-9]
Seçenek 2'nin dördüncü alt seçeneğinde (grup 9) seçenek yaptılar . Bu, normal ifadenin yanlış biçimlendirilmiş posta kodlarıyla eşleşmesini sağlar AAA 1AA
.
Bu sorunu gidermek için, bir sonraki karakter sınıfını isteğe bağlı yapın (ve daha sonra kümenin [0-9]
tam olarak bir kez eşleşmesini sağlayın ):
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?)))) [0-9][A-Za-z]{2})$
^
Sorun 5 - Performans
Bu normal ifade üzerindeki performans son derece zayıf. İlk GIR 0AA
başta, başlangıçta eşleşmesi en az olası desen seçeneğini yerleştirdiler . Diğer posta kodlarına kıyasla kaç kullanıcının bu posta koduna sahip olması muhtemeldir; muhtemelen asla? Bu, normal ifade her kullanıldığında, bir sonraki seçeneğe geçmeden önce bu seçeneğin tüketilmesi gerektiği anlamına gelir. Performansın nasıl etkilendiğini görmek için, orijinal normal ifadenin (35) seçenekleri (22) ters çevirdikten sonra aynı normal ifadeye karşı attığı adım sayısını kontrol edin .
Performansla ilgili ikinci sorun, tüm normal ifadenin yapılandırılma şeklidir. Başarısız olursa, her seçenek üzerinde geriye dönük izleme yoktur. Mevcut normal ifadenin yapılandırılma şekli büyük ölçüde basitleştirilebilir. Bunun için Yanıt bölümünde bir düzeltme sağlarım.
Problem 6 - Mekanlar
Kullanımdaki normal ifadeye bakın
Bu, kendi başına bir sorun olarak görülmeyebilir , ancak çoğu geliştirici için endişe yaratmaktadır. Normal ifadedeki boşluklar isteğe bağlı değildir, yani posta kodlarını giren kullanıcıların posta koduna boşluk bırakmaları gerekir. Bu, ?
isteğe bağlı hale getirmek için boşluklardan sonra ekleyerek kolay bir düzeltmedir . Düzeltme için Yanıt bölümüne bakın .
Cevap
1. Birleşik Krallık Hükümetinin Regex'ini Düzeltmek
Sorunlar bölümünde ana hatlarıyla belirtilen tüm sorunların düzeltilmesi ve desenin basitleştirilmesi aşağıdaki, daha kısa ve daha özlü desen verir. Ayrıca, posta kodunu bir bütün olarak doğruladığımızdan (tek tek parçalar değil) grupların çoğunu kaldırabiliriz:
Kullanımdaki normal ifadeye bakın
^([A-Za-z][A-Ha-hJ-Yj-y]?[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})$
Bu ayrıca, vakaların birinden (büyük veya küçük harf) tüm aralıkları kaldırarak ve büyük / küçük harfe duyarlı olmayan bir bayrak kullanarak kısaltılabilir. Not : Bazı dillerde bir dil yoktur, bu yüzden yukarıdaki uzun dili kullanın. Her dil büyük / küçük harf duyarsızlığı bayrağını farklı uygular.
Kullanımdaki normal ifadeye bakın .
^([A-Z][A-HJ-Y]?[0-9][A-Z0-9]? ?[0-9][A-Z]{2}|GIR ?0A{2})$
Tekrar yerine kısa [0-9]
olan \d
(senin regex motoru destekliyorsa):
Kullanımdaki normal ifadeye bakın .
^([A-Z][A-HJ-Y]?\d[A-Z\d]? ?\d[A-Z]{2}|GIR ?0A{2})$
2. Basitleştirilmiş Desenler
Belirli alfabetik karakterler sağlanmadan aşağıdakiler kullanılabilir ( 1'deki basitleştirmeleri aklınızda bulundurun . İngiltere Hükümeti'nin Regex'inin düzeltilmesi de burada uygulanmıştır):
Kullanımdaki normal ifadeye bakın .
^([A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}|GIR ?0A{2})$
Ve özel durumu önemsemiyorsanız daha da fazlası GIR 0AA
:
^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$
3. Karmaşık Desenler
Yeni Alanlar, İlçeler ve Alt ilçeler herhangi bir zamanda görünebileceğinden bir posta kodunun aşırı doğrulanmasını önermem. Potansiyel olarak ne yapacağımı önereceğim , kenar durumlarda destek eklendi. Bazı özel durumlar mevcuttur ve bu Wikipedia makalesinde ana hatlarıyla verilmiştir .
İşte 3 (3.1, 3.2, 3.3) alt bölümlerini içeren karmaşık düzenli ifadeler .
Düzenlere ilgili olarak İngiltere Hükümeti Regex Tespit 1. :
Kullanımdaki normal ifadeye bakın
^(([A-Z][A-HJ-Y]?\d[A-Z\d]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?\d[A-Z]{2}|BFPO ?\d{1,4}|(KY\d|MSR|VG|AI)[ -]?\d{4}|[A-Z]{2} ?\d{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$
Ve 2. ile ilgili olarak : Basitleştirilmiş Kalıplar :
Kullanımdaki normal ifadeye bakın
^(([A-Z]{1,2}\d[A-Z\d]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?\d[A-Z]{2}|BFPO ?\d{1,4}|(KY\d|MSR|VG|AI)[ -]?\d{4}|[A-Z]{2} ?\d{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$
3.1 İngiliz Denizaşırı Toprakları
Wikipedia makalesinde şu anda belirtiliyor (bazı biçimler biraz basitleştirilmiş):
AI-1111
: Anguila
ASCN 1ZZ
: Yükselme adası
STHL 1ZZ
: Saint Helena
TDCU 1ZZ
: Tristan da Cunha
BBND 1ZZ
: Britanya Hint Okyanusu Toprakları
BIQQ 1ZZ
: Britanya Antarktika Bölgesi
FIQQ 1ZZ
: Falkland adaları
GX11 1ZZ
: Cebelitarık
PCRN 1ZZ
: Pitcairn Adaları
SIQQ 1ZZ
: Güney Georgia ve Güney Sandwich Adaları
TKCA 1ZZ
: Turks ve Caicos Adaları
BFPO 11
: Akrotiri ve Dhekelia
ZZ 11
& GE CX
: Bermuda ( bu belgeye göre )
KY1-1111
: Cayman Adaları ( bu belgeye göre )
VG1111
: İngiliz Virgin Adaları ( bu belgeye göre )
MSR 1111
: Montserrat ( bu belgeye göre )
Yalnızca İngiliz Denizaşırı Toprakları ile eşleşecek her şeyi kapsayan bir normal ifade şöyle görünebilir:
Kullanımdaki normal ifadeye bakın .
^((ASCN|STHL|TDCU|BBND|[BFS]IQQ|GX\d{2}|PCRN|TKCA) ?\d[A-Z]{2}|(KY\d|MSR|VG|AI)[ -]?\d{4}|(BFPO|[A-Z]{2}) ?\d{2}|GE ?CX)$
3.2 İngiliz Kuvvetleri Postanesi
Son zamanlarda İngiliz posta kodu sistemiyle BF#
( #
bir sayıyı temsil eder) daha iyi hizalanacak şekilde değiştirilmelerine rağmen , isteğe bağlı alternatif posta kodları olarak kabul edilirler . Bu posta kodları BFPO
, ardından 1-4 basamak biçimini izler (düzenler) :
Kullanımdaki normal ifadeye bakın
^BFPO ?\d{1,4}$
3.3 Noel Baba?
Noel Baba ile başka bir özel durum daha var (diğer cevaplarda belirtildiği gibi): SAN TA1
geçerli bir posta kodu. Bunun için bir normal ifade çok basittir:
^SAN ?TA1$