不使用正则表达式的英国(GB)邮政编码验证 [英] United Kingdom (GB) postal code validation without regex
问题描述
我尝试了几种正则表达式,但有时仍然拒绝了一些有效的邮政编码.
I have tried several regexes and still some valid postal codes sometimes get rejected.
搜索互联网,维基百科和SO,我只能找到正则表达式验证解决方案.
Searching the internet, Wikipedia and SO, I could only find regex validation solutions.
是否存在不使用正则表达式的验证方法?我认为,使用任何一种语言,移植起来都很容易.
Is there a validation method which does not use regex? In any language, I guess it would be easy to port.
我认为最简单的方法是将其与邮政编码数据库进行比较,但这需要从可靠的来源进行定期维护和更新.
I supose the easiest would be to compare against a postal code database, yet that would need to be maintained and updated periodically from a reliable source.
为了帮助将来的访问者并使您免于发布更多正则表达式,以下是我已经测试过的正则表达式(截至2013-04-24),可在Code Point(
To help future visitors and keep you from posting any more regexes, here's a regex which I have tested (as of 2013-04-24) to work for all postal codes in Code Point (see @Mikkel Løkke's answer):
//PHP PCRE (it was on Wikipedia, it isn't there anymore; I might have modified it, don't remember).
$strPostalCode=preg_replace("/[\s]/", "", $strPostalCode);
$bValid=preg_match("/^(GIR 0AA)|(((A[BL]|B[ABDHLNRSTX]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|((E|N|NW|SE|SW|W)1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|(SW|W)([2-9]|[1-9][0-9])|EC[1-9][0-9])[0-9][ABD-HJLNP-UW-Z]{2})$/i", $strPostalCode);
推荐答案
我正在根据 wiki页面编写此答案. a>.
I'm writing this answer based on the wiki page.
在检查验证部分时,似乎有6种格式(A =字母和9 =位数):
When checking on the validation part, it seems that there are 6 type of formats (A = letter and 9 = digit):
AA9A 9AA AA9A9AA AA9A9AA
A9A 9AA Removing space A9A9AA order it AA999AA
A9 9AA ------------------> A99AA -------------> AA99AA
A99 9AA A999AA A9A9AA
AA9 9AA AA99AA A999AA
AA99 9AA AA999AA A99AA
我们可以看到,长度可能从5到7不等,我们必须考虑某些特殊情况如果我们愿意.
As we can see, the length may vary from 5 to 7 and we have to take in account some special cases if we want to.
因此,我们正在编码的函数必须执行以下操作:
So the function we are coding has to do the following:
- 删除空格并转换为大写(或小写).
- 检查输入是否为异常,如果输入为异常,则应返回 valid
- 检查输入的长度是否为4 < 长度< 8.
- 检查其是否为有效的邮政编码.
- Remove spaces and convert to uppercase (or lower case).
- Check if the input is an exception, if it is it should return valid
- Check if the input's length is 4 < length < 8.
- Check if it's a valid postcode.
最后一部分很棘手,但我们将其按长度分为3个部分,以进行概述:
The last part is tricky, but we will split it in 3 sections by length for some overview:
- 长度= 7: AA9A9AA 和 AA999AA
- 长度= 6: AA99AA , A9A9AA 和 A999AA
- 长度= 5: A99AA
- Length = 7: AA9A9AA and AA999AA
- Length = 6: AA99AA, A9A9AA and A999AA
- Length = 5: A99AA
为此,我们将使用switch()
.从现在开始,只需要逐个字符地检查是正确的字母还是数字即可.
For this we will be using a switch()
. From now on it's just a matter of checking character by character if it's a letter or a number on the right place.
因此,让我们看一下我们的PHP实现:
So let's take a look at our PHP implementation:
function check_uk_postcode($string){
// Start config
$valid_return_value = 'valid';
$invalid_return_value = 'invalid';
$exceptions = array('BS981TL', 'BX11LT', 'BX21LB', 'BX32BB', 'BX55AT', 'CF101BH', 'CF991NA', 'DE993GG', 'DH981BT', 'DH991NS', 'E161XL', 'E202AQ', 'E202BB', 'E202ST', 'E203BS', 'E203EL', 'E203ET', 'E203HB', 'E203HY', 'E981SN', 'E981ST', 'E981TT', 'EC2N2DB', 'EC4Y0HQ', 'EH991SP', 'G581SB', 'GIR0AA', 'IV212LR', 'L304GB', 'LS981FD', 'N19GU', 'N811ER', 'NG801EH', 'NG801LH', 'NG801RH', 'NG801TH', 'SE18UJ', 'SN381NW', 'SW1A0AA', 'SW1A0PW', 'SW1A1AA', 'SW1A2AA', 'SW1P3EU', 'SW1W0DT', 'TW89GS', 'W1A1AA', 'W1D4FA', 'W1N4DJ');
// Add Overseas territories ?
array_push($exceptions, 'AI-2640', 'ASCN1ZZ', 'STHL1ZZ', 'TDCU1ZZ', 'BBND1ZZ', 'BIQQ1ZZ', 'FIQQ1ZZ', 'GX111AA', 'PCRN1ZZ', 'SIQQ1ZZ', 'TKCA1ZZ');
// End config
$string = strtoupper(preg_replace('/\s/', '', $string)); // Remove the spaces and convert to uppercase.
$exceptions = array_flip($exceptions);
if(isset($exceptions[$string])){return $valid_return_value;} // Check for valid exception
$length = strlen($string);
if($length < 5 || $length > 7){return $invalid_return_value;} // Check for invalid length
$letters = array_flip(range('A', 'Z')); // An array of letters as keys
$numbers = array_flip(range(0, 9)); // An array of numbers as keys
switch($length){
case 7:
if(!isset($letters[$string[0]], $letters[$string[1]], $numbers[$string[2]], $numbers[$string[4]], $letters[$string[5]], $letters[$string[6]])){break;}
if(isset($letters[$string[3]]) || isset($numbers[$string[3]])){
return $valid_return_value;
}
break;
case 6:
if(!isset($letters[$string[0]], $numbers[$string[3]], $letters[$string[4]], $letters[$string[5]])){break;}
if(isset($letters[$string[1]], $numbers[$string[2]]) || isset($numbers[$string[1]], $letters[$string[2]]) || isset($numbers[$string[1]], $numbers[$string[2]])){
return $valid_return_value;
}
break;
case 5:
if(isset($letters[$string[0]], $numbers[$string[1]], $numbers[$string[2]], $letters[$string[3]], $letters[$string[4]])){
return $valid_return_value;
}
break;
}
return $invalid_return_value;
}
注意,我尚未添加 British Forces Post Office 和非地理代码.
用法:
echo check_uk_postcode('AE3A 6AR').'<br>'; // valid
echo check_uk_postcode('Z9 9BA').'<br>'; // valid
echo check_uk_postcode('AE3A6AR').'<br>'; // valid
echo check_uk_postcode('EE34 6FR').'<br>'; // valid
echo check_uk_postcode('A23A 7AR').'<br>'; // invalid
echo check_uk_postcode('A23A 7AR').'<br>'; // invalid
echo check_uk_postcode('WA3334E').'<br>'; // invalid
echo check_uk_postcode('A2 AAR').'<br>'; // invalid
这篇关于不使用正则表达式的英国(GB)邮政编码验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!