仅获取英国邮政编码的第一部分

时间:2015-04-02 10:02:33

标签: php regex postal-code

我试图从一个字符串中获取英国邮政编码的第一部分,该字符串可能只包含邮政编码的第一部分或其中的完整邮政编码。我努力使其发挥作用。如果通过使用预测输入完整的邮政编码,我就能使用它,但我似乎无法使前瞻可选,所以如果只输入邮政编码的第一部分,它就是匹配。

到目前为止我的正则表达式是([A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPS-UW])(?=( ?[0-9][ABD-HJLNP-UW-Z]{2})))

我有几个必须匹配的邮政编码,这些是使用上述正则表达式的结果:

A10EA     - Should match and does
A1        - Should match but doesn't
A10 0EA   - Should match and does
A10       - Should match but doesn't
BH18 1AE  - Should match and does
BH18AE    - Should match and does
EC1M 6HJ  - Should match and does
EC1M      - Should match but doesn't
Z10 2EV   - Shouldn't match and doesn't
QE3 6DA   - Shouldn't match but matches E3 6DA

有人可以帮我解决这个问题吗?

我一直在工作的RegEx是来自邮局的官方人员:

/^(GIR ?0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPS-UW]) ?[0-9][ABD-HJLNP-UW-Z]{2})$/i

在任何人将此标记为PHP Find first part of UK postcode when full or part can be entered的副本之前,它不是。这个问题的答案不起作用,请参阅我对答案的评论。

2 个答案:

答案 0 :(得分:1)

根据this wiki page,帖子代码始终以&#39位数字母'结尾,这将是\d\w\w$的正则表达式模式。现在我们知道如何发现目标是什么,我们只想捕捉其余部分。

(\S*)\s*\d\w\w$这样的模式会起作用。这将捕获上半部分,并确保您没有获得最后的数字字母部分。它将通过获取任何不是空格的东西来捕获第一部分,即只有字母和数字。

为了充分解释这一点,我们正在捕捉括号()\S表示任何一个非空格字符,\S*就是我们能得到的所有内容。所以(\S*)捕捉到空间角色的所有内容,但如果用户没有输入,则会捕获所有内容。我提供的完整正则表达式还将尝试捕获任何空白区域,一个数字,两个字母,字符串末尾'这将确保AA999AA分为AA999AA

我也注意到你的问题表明你可能实际上没有第二部分。我想你可以通过检查字符串长度来解决这个问题。如果修剪空格并且长度小于5个字符,则必须只有第一个部分,因此不需要任何正则表达式。


免责声明这对Anguillan邮政编码无效。为了支持他们的邮政编码,我认为(\ S *)\ s *(?:\ d \ w \ w | - \ d {4})$也可以。

答案 1 :(得分:0)

我一直在以错误的方式看待这个问题。我想得到邮政编码的第一部分并删除第二部分(如果存在),所以为什么不首先验证邮政编码,然后检查结束并在必要时将其剥离。

我已经验证了邮政编码,这是我已经拥有的代码:

$validate = Validation::factory(array('postcode' => $postcode));
$validate->rule('postcode', 'not_empty');
$validate->rule('postcode', 'regex', array(':value', '/^(GIR ?(0AA)?|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPS-UW]) ?([0-9][ABD-HJLNP-UW-Z]{2})?)$/i'));
if ( ! $validate->check())
{
    $postcode = '';
}

所以现在我已经在此之后添加了:

if ($postcode)
{
    $short_postcode = $postcode;
    // Check for an end section and then if present, remove it
    if (preg_match('/ ?([0-9])[ABD-HJLNP-UW-Z]{2})$/i', $postcode, $match, PREG_OFFSET_CAPTURE))
    {
        $short_postcode = substr($postcode, 0, $match[0][1]);
    }
}

这只留下了邮政编码的第一部分,这就是我想要的。 This Eval.in显示它适用于我的问题中的所有示例。