2017-10-28 157 views
0

我使用正則表達式supplied by the British government驗證英國郵政編碼。我的測試目前看起來是這樣的:匹配整個字符串與正則表達式

const postcodeRegex = /^([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})$/g; 

console.log(postcodeRegex.test('s75ed')); // returns true 
console.log(postcodeRegex.test('s75ed555555')); // returns false 
console.log(postcodeRegex.test('555555s75ed')); // returns true 

第2個控制檯日誌是正確的,但我希望第3次返回false。當模式在字符串的末尾匹配時,測試返回true,但是這允許在字符串的開頭處有任何亂碼,這意味着整個字符串是一個無效的郵編。

如何嚴格匹配整個字符串的模式?

+0

此模式是否直接從英國政府複製?如果是這樣,我很驚訝他們沒有正確地測試它自己。似乎有幾個缺陷:o) – agrm

+0

@agrm是直接從.gov網站上發佈的文檔。我知道這是令人難以置信的,但這就是政府所做的一切。 – Coop

+0

@agrm我添加了一個鏈接到PDF。 – melpomene

回答

3

你的正則表達式具有這種形狀:^A|B$。 看來你沒有想到這會匹配AgibberishgibberishB,而你實際上是在尋找^(A|B)$。 這樣寫, 它只會匹配AB, 它不會匹配AgibberishgibberishB

順便說一句,正則表達式的這部分看起來像一個bug:[AZa-z]。 你可能意思是[A-Za-z]

事實上,正則表達式中的所有字母都以大寫和小寫形式出現。因此,如果添加i標誌並消除其中一種情況,則可以簡化一點點:

const postcodeRegex = /^((gir 0a{2})|((([a-z][0-9]{1,2})|(([a-z][a-hj-y][0-9]{1,2})|(([a-z][0-9][a-z])|([a-z][a-hj-y][0-9]?[a-z]))))[0-9][a-z]{2}))$/gi; 
+0

太棒了,這解決了比我想象的更多的問題。相信政府爲此提供不正確的模式。 – Coop

+0

即使更正後的正則表達式也不能完全驗證郵政編碼。某些字母(如Q)不能出現在第一個位置。我從未使用這封信。只有某些組合是有效的,第一個位置上的G區本身是好的,但只有GL,GU和GY對第二個字母有效。等等。 – Nick

2

如果再加上一些空白和縮進,您正則表達式是這樣的:

^([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})$ 

即只有第一個選項被錨定到字符串的開頭(^),並且只有第二個選項被錨定到字符串的末尾($)。

你可以用在(非捕獲)組,而不是整個事情:

^(?:...|...)$ 
+1

輝煌,新的分組似乎解決了這個問題。我很驚訝英國政府公開分享這個不正確的正則表達式模式...等等,我一點都不驚訝。 – Coop