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

Posted

技术标签:

【中文标题】仅获取英国邮政编码的第一部分【英文标题】:Get first part of UK postcode only 【发布时间】:2015-04-02 10:02:32 【问题描述】:

我正在尝试从一个字符串中获取英国邮政编码的第一部分,该字符串中可能只有邮政编码的第一部分或完整的邮政编码。我正在努力让它发挥作用。如果通过使用前瞻输入完整的邮政编码,我已经让它工作了,但我似乎无法将前瞻设为可选,所以如果只输入邮政编码的第一部分,它就会匹配。

到目前为止,我的正则表达式是([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

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

我一直使用的正则表达式是邮局的官方正则表达式:

/^(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 的副本之前,事实并非如此。该问题的答案不起作用,请参阅我对答案的评论。

【问题讨论】:

您能描述一下英国邮政编码的结构吗? 我已经添加了邮局为英国邮政编码提供的官方正则表达式,我不知道如何描述这个结构。 我找到了this,但我不确定它是否相关。最好不要使用正则表达式并为此编写一个简单的函数,因为它已经相当复杂了。 另外,如果您只想防止用户输入无效的邮政编码,我认为简单的验证就足够了。前段时间我无法在运营商的网站上购买手机,因为它的数据库中没有街道名称,因此不让我继续。 不,我已经这样做了。我有一个邮政编码前半部分的数据库,我需要获取用户输入的邮政编码,如果后半部分存在,则修剪后半部分,然后在数据库中检查以获取对应的ID。 【参考方案1】:

根据this wiki page,邮政编码始终以“数字字母”结尾,这将是\d\w\w$ 的正则表达式模式。现在我们知道如何发现结尾了,我们只想捕捉其余部分。

(\S*)\s*\d\w\w$ 这样的模式可以工作。这将捕获前半部分,并确保您没有得到最后一个“数字字母字母”部分。它将通过获取任何非空格(即只有字母和数字)来捕获第一部分。

为了充分解释这一点,括号() 是我们正在捕获的内容。 \S 表示'任何一个非空白字符,\S* 是我们能得到的全部。所以(\S*) 捕获所有内容,直到一个空格字符,但如果用户不输入,则会捕获所有内容。我提供的完整正则表达式还将尝试捕获“任何空格、一个数字、两个字母、字符串结尾”,这将确保 AA999AA 被拆分为 AA999AA

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


免责声明这不适用于安圭拉邮政编码。为了也支持他们的邮政编码,我认为 (\S*)\s*(?:\d\w\w|-\d4)$ 会起作用。

【讨论】:

我确实有所有第一部分的完整列表,但即使该列表 A1A10 都有效,我需要找到一种方法来知道第一个是 @ 987654333@ 而不是A10,到目前为止,我想出的任何正则表达式如果没有空格,总是说它是A10,我不能保证有空格。 @Styphon 完全重写,这应该可以帮助你。 我仍然遇到同样的问题?([0-9][ABD-HJLNP-UW-Z]2)?) 做同样的事情,匹配一个可选的空格、一个数字和两个字母(但只有有效的字母)。最后的问号使它成为可选的,但如果它在那里,我怎么能告诉正则表达式只选择前半部分?【参考方案2】:

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

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

$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 表明它适用于我问题中的所有示例。

【讨论】:

如果您已经验证了您的字符串是一个有效的邮政编码,那么删除第二部分可以只是\d\w\w,因为它更容易阅读。我也认为正式验证是过度设计的,尽管我当然不知道你的需求。您是否只需要验证它“像”一个邮政编码还是它实际上是一个真实的邮政编码 您还应该能够在一个正则表达式中同时验证和捕获(第一部分)。 @thecoshman 我无法捕捉到第一部分,这就是我首先问这个问题的原因。我无法让它正确验证所有内容。我使用正式验证是因为它必须是有效的邮政编码,而不仅仅是邮政编码的格式。

以上是关于仅获取英国邮政编码的第一部分的主要内容,如果未能解决你的问题,请参考以下文章

如何过滤英国邮政编码

Redshift中的英国邮政编码区

正则表达式匹配英国邮政编码的前半部分

邮政编码的第一部分

在最后三个字符前插入空格

Javascript-将onclick设置为仅页面的第一部分