Código Postal do Reino Unido (Abrangente)

Eu estou atrás de um regex que irá validar um CEP completo e complexo apenas dentro de uma string de input. Todos os formulários incomuns de código postal devem ser cobertos, assim como o usual. Por exemplo:

Fósforos

  • CW3 9SS
  • SE5 0EG
  • SE50EG
  • se5 0eg
  • WC2H 7LT

Sem correspondência

  • aWC2H 7LT
  • WC2H 7LTa
  • WC2H

Há alguma expressão oficial ou semi-oficial em uso para esse tipo de coisa? Algum outro conselho para formatá-los e armazená-los em um database?

Eu recomendaria dar uma olhada no Padrão de Dados do Governo do Reino Unido para códigos postais [link now dead; arquivo de XML , veja Wikipedia para discussão]. Há uma breve descrição sobre os dados e o esquema xml anexado fornece uma expressão regular. Pode não ser exatamente o que você quer, mas seria um bom ponto de partida. O RegEx difere do XML ligeiramente, já que um caracter P na terceira posição no formato A9A 9AA é permitido pela definição dada.

O RegEx fornecido pelo governo do Reino Unido foi:

([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]?))))\s?[0-9][A-Za-z]{2}) 

Como apontado na discussão da Wikipedia, isso permitirá alguns códigos postais não-reais (por exemplo, aqueles que começam com AA, ZY) e eles fornecem um teste mais rigoroso que você poderia tentar.

Parece que vamos usar ^(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})$ , que uma vers ligeiramente modificada do que sugerido por Minglis acima.

No entanto, teremos que investigar exatamente quais são as regras, já que as várias soluções listadas acima parecem aplicar regras diferentes sobre quais letras são permitidas.

Depois de alguma pesquisa, encontramos mais algumas informações. Aparentemente, uma página em ‘govtalk.gov.uk’ aponta para uma especificação de código postal govtalk-postcodes . Isso aponta para um esquema XML no XML Schema que fornece uma instrução ‘pseudo-regex’ das regras de código postal.

Nós pegamos isso e trabalhamos um pouco para nos dar a seguinte expressão:

 ^((GIR &0AA)|((([A-PR-UWYZ][A-HK-Y]?[0-9][0-9]?)|(([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y]))) &[0-9][ABD-HJLNP-UW-Z]{2}))$ 

Isso torna os espaços opcionais, mas limita você a um espaço (substitua o ‘&’ por ‘{0,} para espaços ilimitados). Assume que todo o texto deve estar em maiúsculas.

Se você quiser permitir letras minúsculas, com qualquer número de espaços, use:

 ^(([gG][iI][rR] {0,}0[aA]{2})|((([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y]?[0-9][0-9]?)|(([a-pr-uwyzA-PR-UWYZ][0-9][a-hjkstuwA-HJKSTUW])|([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y][0-9][abehmnprv-yABEHMNPRV-Y]))) {0,}[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2}))$ 

Isso não cobre territórios no exterior e apenas reforça o formato, NÃO a existência de áreas diferentes. Baseia-se nas seguintes regras:

Pode aceitar os seguintes formatos:

  • “GIR 0AA”
  • A9 9ZZ
  • A99 9ZZ
  • AB9 9ZZ
  • AB99 9ZZ
  • A9C 9ZZ
  • AD9E 9ZZ

Onde:

  • 9 pode ser qualquer número de dígito único.
  • A pode ser qualquer letra, exceto Q, V ou X.
  • B pode ser qualquer letra exceto I, J ou Z.
  • C pode ser qualquer letra exceto I, L, M, N, O, P, Q, R, V, X, Y ou Z.
  • D pode ser qualquer letra exceto I, J ou Z.
  • E pode ser qualquer um de A, B, E, H, M, N, P, R, V, W, X ou Y.
  • Z pode ser qualquer letra exceto para C, I, K, M, O ou V.

Muitas felicidades

Colin

Não existe uma expressão regular abrangente de código postal do Reino Unido que seja capaz de validar um código postal. Você pode verificar se um código postal está no formato correto usando uma expressão regular; não que realmente exista.

Postcodes são arbitrariamente complexos e mudando constantemente. Por exemplo, o código de saída W1 não tem, e nunca pode, ter todos os números entre 1 e 99, para cada área de código postal.

Você não pode esperar o que existe atualmente para ser verdade para sempre. Como exemplo, em 1990, os Correios decidiram que Aberdeen estava ficando um pouco lotado. Eles adicionaram um 0 ao final de AB1-5, tornando AB10-50 e, em seguida, criou um número de códigos postais entre estes.

Sempre que uma nova rua é criada, um novo código postal é criado. Faz parte do processo de obtenção de permissão para construir; as autoridades locais são obrigadas a mantê-lo atualizado com os Correios (não que todos eles façam).

Além disso, como observado por vários outros usuários, há os códigos postais especiais, como Girobank, GIR 0AA, e o de cartas para Santa, SAN TA1 – você provavelmente não quer postar nada lá, mas não parece ser coberto por qualquer outra resposta.

Depois, há os códigos postais da BFPO, que agora estão mudando para um formato mais padrão . Ambos os formatos serão válidos. Por fim, há os territórios ultramarinos que originam a Wikipedia .

 + ---------- + -------------------------------------- -------- +
 |  CEP |  Localização |
 + ---------- + -------------------------------------- -------- +
 |  AI-2640 |  Anguilla |
 |  ASCN 1ZZ |  Ilha da Ascensão |
 |  STHL 1ZZ |  Santa Helena |
 |  TDCU 1ZZ |  Tristan da Cunha |
 |  BBND 1ZZ |  Território Britânico do Oceano Índico |
 |  BIQQ 1ZZ |  Território Antártico Britânico |
 |  FIQQ 1ZZ |  Ilhas Malvinas |
 |  GX11 1AA |  Gibraltar |
 |  PCRN 1ZZ |  Ilhas Pitcairn |
 |  SIQQ 1ZZ |  Ilhas Geórgia do Sul e Sandwich do Sul |
 |  TKCA 1ZZ |  Ilhas Turks e Caicos |
 + ---------- + -------------------------------------- -------- + 

Em seguida, você deve levar em conta que o Reino Unido “exportou” seu sistema de código postal para muitos lugares no mundo. Qualquer coisa que valide um código postal “Reino Unido” também validará os códigos postais de vários outros países.

Se você quiser validar um código postal do Reino Unido, a maneira mais segura de fazer isso é usar uma pesquisa dos códigos postais atuais. Há uma série de opções:

  • A Pesquisa Ordinária lança o Code-Point Open sob uma licença de dados abertos. Vai ser um pouco atrás dos tempos, mas é grátis. Isto irá (provavelmente – não me lembro) não include dados da Irlanda do Norte, uma vez que o Inquérito Ordinário não tem qualquer missão nesse local. O mapeamento na Irlanda do Norte é conduzido pela Pesquisa Ordinária da Irlanda do Norte e eles têm seu produto Pointer separado e pago. Você poderia usar isso e acrescentar os poucos que não são abordados com bastante facilidade.

  • O Royal Mail libera o arquivo de endereço de código postal (Postcode Address File – PAF) , isso inclui o BFPO, que não tenho certeza se o Code-Point Open faz isso. É atualizado regularmente, mas custa dinheiro (e eles podem ser absolutamente dizer sobre isso às vezes). O PAF inclui o endereço completo em vez de apenas códigos postais e vem com o seu próprio Guia de Programadores . O Grupo de Usuários de Dados Abertos (ODUG) está atualmente fazendo lobby para ter o PAF liberado gratuitamente, aqui está uma descrição de sua posição .

  • Por fim, há AddressBase . Esta é uma colaboração entre a Pesquisa de Ordernância, Autoridades Locais, Royal Mail e uma empresa correspondente para criar um diretório definitivo de todas as informações sobre todos os endereços do Reino Unido (eles também tiveram bastante sucesso). É pago, mas se você estiver trabalhando com uma autoridade local, departamento do governo ou serviço governamental, é livre para eles usarem. Há muito mais informações do que apenas códigos postais incluídos.

Analisei algumas das respostas acima e recomendo que não use o padrão da resposta do @Dan (c. Dez 15 ’10) , já que ele sinaliza incorretamente quase 0,4% dos códigos postais válidos, enquanto os outros não .

Levantamento de Ordnance fornece serviço chamado Code Point Open que:

contém uma lista de todas as unidades de código postal atuais em Great Britain

Eu corri cada um dos regexs acima contra a lista completa de códigos postais (6 de julho de 2013) desses dados usando o grep :

 cat CSV/*.csv | # Strip leading quotes sed -e 's/^"//g' | # Strip trailing quote and everything after it sed -e 's/".*//g' | # Strip any spaces sed -E -e 's/ +//g' | # Find any lines that do not match the expression grep --invert-match --perl-regexp "$pattern" 

Existem 1.686.202 códigos postais totais.

A seguir, os números de códigos postais válidos que não correspondem a cada $pattern :

 '^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]?[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$' # => 6016 (0.36%) 
 '^(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})$' # => 0 
 '^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|BX|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$' # => 0 

Naturalmente, esses resultados lidam apenas com códigos postais válidos marcados incorretamente como inválidos. Assim:

 '^.*$' # => 0 

Não estou dizendo nada sobre qual padrão é o melhor em relação à filtragem de códigos postais inválidos.

 ^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$ 

Expressão regular para corresponder a códigos postais válidos no Reino Unido. No sistema postal do Reino Unido, nem todas as cartas são usadas em todas as posições (o mesmo com placas de matrícula de veículos) e existem várias regras para governar isso. Esse regex leva em conta essas regras. Detalhes das regras: Primeira metade do código postal Formatos válidos [AZ] [AZ] [0-9] [AZ] [AZ] [AZ] [0-9] [0-9] [AZ] [0-9] [ 0-9] [AZ] [AZ] [0-9] [AZ] [AZ] [AZ] [AZ] [0-9] [AZ] [AZ] [0-9] Exceções Posição – primeiro. Contraint – QVX não usado Position – Second. Contraint – IJZ não utilizado, exceto na posição GIR 0AA – Third. Restrição – AEHMNPRTVXY utilizou apenas Position – Forth. Contraint – ABEHMNPRVWXY Segunda metade do código postal Formatos válidos [0-9] [AZ] [AZ] Exceções Posição – Segunda e Terceira. Contraint – CIKMOV não usado

http://regexlib.com/REDetails.aspx?regexp_id=260

Uma postagem antiga, mas ainda bastante alta nos resultados do Google, então pensei em atualizar. Este documento de 14 de outubro define a expressão regular do código postal do Reino Unido como:

 ^([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})|(([**AZ**az][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$ 

a partir de:

https://www.gov.uk/government/uploads/system/uploads/attachment_data/file/359448/4__Bulk_Data_Transfer_-_additional_validation_valid.pdf

O documento também explica a lógica por trás disso. No entanto, ele tem um erro (em negrito) e também permite que minúsculas, que embora legal não é usual, versão alterada:

 ^(GIR 0AA)|((([AZ][0-9]{1,2})|(([AZ][A-HJ-Y][0-9]{1,2})|(([AZ][0-9][AZ])|([AZ][A-HJ-Y][0-9]?[AZ])))) [0-9][AZ]{2})$ 

Isso funciona com os novos códigos postais de Londres (por exemplo, W1D 5LH) que as versões anteriores não tinham.

A maioria das respostas aqui não funcionou para todos os códigos postais que eu tenho no meu database. Eu finalmente encontrei um que valida com todos, usando o novo regex fornecido pelo governo:

https://www.gov.uk/government/uploads/system/uploads/attachment_data/file/413338/Bulk_Data_Transfer_-_additional_validation_valid_from_March_2015.pdf

Não está em nenhuma das respostas anteriores, então eu postei aqui, caso eles abram o link:

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

ATUALIZAÇÃO: Regex atualizado como apontado por Jamie Bull. Não tenho certeza se foi meu erro copiando ou foi um erro na regex do governo, o link está inativo agora …

ATUALIZAÇÃO: Como os ctwheels foram encontrados, esse regex funciona com o sabor regex do javascript. Veja o comentário dele para um que funciona com o sabor pcre (php).

De acordo com esta tabela da Wikipedia

insira a descrição da imagem aqui

Este padrão cobre todos os casos

 (?:[A-Za-z]\d ?\d[A-Za-z]{2})|(?:[A-Za-z][A-Za-z\d]\d ?\d[A-Za-z]{2})|(?:[A-Za-z]{2}\d{2} ?\d[A-Za-z]{2})|(?:[A-Za-z]\d[A-Za-z] ?\d[A-Za-z]{2})|(?:[A-Za-z]{2}\d[A-Za-z] ?\d[A-Za-z]{2}) 

Ao usá-lo no Android \ Java, use \\ d

Os códigos postais estão sujeitos a alterações, e a única maneira verdadeira de validar um código postal é ter a lista completa de códigos postais e ver se está lá.

Mas expressões regulares são úteis porque elas:

  • são fáceis de usar e implementar
  • são curtos
  • são rápidos de executar
  • são muito fáceis de manter (em comparação com uma lista completa de códigos postais)
  • ainda captura a maioria dos erros de input

Mas expressões regulares tendem a ser difíceis de manter, especialmente para alguém que não surgiu com ele em primeiro lugar. Então deve ser:

  • tão fácil de entender quanto possível
  • relativamente futuro

Isso significa que a maioria das expressões regulares nesta resposta não é boa o suficiente. Por exemplo, eu posso ver que [A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y] vai combinar uma área de código postal do formulário AA1A – mas vai ser uma dor no pescoço se e quando uma nova área de código postal for adicionada, porque é difícil entender quais áreas de código postal correspondem.

Também quero que minha expressão regular corresponda à primeira e à segunda metade do código postal como correspondências entre parênteses.

Então eu vim com isso:

 (GIR(?=\s*0AA)|(?:[BEGLMNSW]|[AZ]{2})[0-9](?:[0-9]|(?<=N1|E1|SE1|SW1|W1|NW1|EC[0-9]|WC[0-9])[A-HJ-NP-Z])?)\s*([0-9][ABD-HJLNP-UW-Z]{2}) 

No formato PCRE, pode ser escrito da seguinte forma:

 /^ ( GIR(?=\s*0AA) # Match the special postcode "GIR 0AA" | (?: [BEGLMNSW] | # There are 8 single-letter postcode areas [AZ]{2} # All other postcode areas have two letters ) [0-9] # There is always at least one number after the postcode area (?: [0-9] # And an optional extra number | # Only certain postcode areas can have an extra letter after the number (?<=N1|E1|SE1|SW1|W1|NW1|EC[0-9]|WC[0-9]) [A-HJ-NP-Z] # Possible letters here may change, but [IO] will never be used )? ) \s* ([0-9][ABD-HJLNP-UW-Z]{2}) # The last two letters cannot be [CIKMOV] $/x 

Para mim, este é o equilíbrio certo entre validar o máximo possível, ao mesmo tempo em que protege o futuro e facilita a manutenção.

Eu tenho procurado por um código postal do Reino Unido para o último dia ou assim e tropeçou neste segmento. Eu trabalhei meu caminho através da maioria das sugestões acima e nenhum deles funcionou para mim, então eu vim com meu próprio regex que, tanto quanto eu sei, captura todos os códigos postais válidos no Reino Unido a partir de janeiro ’13 (de acordo com a literatura mais recente da o Correio Real).

O regex e alguns código PHP simples verificando código postal é postado abaixo. OBSERVAÇÃO: – Permite códigos postais de letras maiúsculas ou minúsculas e a anomalia GIR 0AA, mas para lidar com a presença mais do que provável de um espaço no meio de um código postal inserido, também faz uso de um str_replace simples para remover o espaço antes de testar contra o regex. Quaisquer discrepâncias além daquelas e do próprio Royal Mail nem sequer os mencionam em sua literatura (consulte http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf e comece a ler a partir da página 17) !

Nota: Na própria literatura do Royal Mail (link acima) existe uma ligeira ambigüidade em torno da 3ª e 4ª posições e as exceções em vigor se esses caracteres forem letras. Entrei em contato com o Royal Mail diretamente para esclarecê-lo e em suas próprias palavras “Uma carta na 4ª posição do Código Externo com o formato AANA NAA não tem exceções e as exceções da 3ª posição aplicam-se apenas à última letra do Código de Saída com a formato ANA NAA. ” Direto da boca do cavalo!

 "; } else { echo "$postcode2check is not a valid postcode
"; } ?>

Espero que ajude quem mais se deparar com este segmento em busca de uma solução.

Este é o regex que o Google veicula em seu domínio i18napis.appspot.com :

 GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|BX|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4} 

Aqui está um regex baseado no formato especificado nos documentos que estão vinculados à resposta do marcj:

 /^[AZ]{1,2}[0-9][0-9A-Z]? ?[0-9][AZ]{2}$/ 

A única diferença entre isso e as especificações é que os últimos 2 caracteres não podem estar em [CIKMOV] de acordo com as especificações.

Edit: Aqui está outra versão que faz teste para as limitações de caracteres à direita.

 /^[AZ]{1,2}[0-9][0-9A-Z]? ?[0-9][A-BD-HJLNP-UW-Z]{2}$/ 

Alguns dos regexs acima são um pouco restritivos. Observe o código postal genuíno: “W1K 7AA” falharia, dada a regra “Posição 3 – AEHMNPRTVXY usado apenas” acima, pois “K” não seria permitido.

o regex:

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

Parece um pouco mais preciso, consulte o artigo da Wikipedia intitulado “Códigos postais no Reino Unido” .

Observe que essa regex requer apenas caracteres maiúsculos.

A grande questão é se você está restringindo a input do usuário para permitir apenas os códigos postais que realmente existem ou se você está simplesmente tentando impedir que os usuários insiram lixo completo nos campos do formulário. Corrigir correspondentemente todos os códigos postais possíveis e testá-los no futuro é um quebra-cabeças mais difícil, e provavelmente não vale a pena, a menos que você seja o HMRC.

Regras básicas:

 ^[AZ]{1,2}[0-9R][0-9A-Z]? [0-9][ABD-HJLNP-UW-Z]{2}$ 

Os códigos postais no Reino Unido (ou códigos postais, como são chamados) são compostos de cinco a sete caracteres alfanuméricos separados por um espaço. As regras que cobrem quais personagens podem aparecer em posições particulares são bastante complicadas e repletas de exceções. A expressão regular apenas mostrada, portanto, adere às regras básicas.

Regras completas:

Se você precisa de um regex que marque todas as checkboxs para as regras de código postal em detrimento da legibilidade, aqui vai:

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

Fonte: https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch04s16.html

Testado contra o database de nossos clientes e parece perfeitamente preciso.

Primeira metade do código postal Formatos válidos

  • [AZ] [AZ] [0-9] [AZ]
  • [AZ] [AZ] [0-9] [0-9]
  • [AZ] [0-9] [0-9]
  • [AZ] [AZ] [0-9]
  • [AZ] [AZ] [AZ]
  • [AZ] [0-9] [AZ]
  • [AZ] [0-9]

Exceções
Posição 1 – QVX não usado
Posição 2 – IJZ não utilizada, exceto na GIR 0AA
Posição 3 – AEHMNPRTVXY usado somente
Posição 4 – ABEHMNPRVWXY

Segunda metade do código postal

  • [0-9] [AZ] [AZ]

Exceções
Posição 2 + 3 – CIKMOV não usado

Lembre-se de que nem todos os códigos possíveis são usados, portanto, essa lista é uma condição necessária, mas não suficiente, para um código válido. Pode ser mais fácil simplesmente combinar com uma lista de todos os códigos válidos?

Para verificar um código postal está em um formato válido de acordo com o guia do programador do Royal Mail:

  |----------------------------outward code------------------------------| |------inward code-----| #special↓ α1 α2 AAN AANA AANN AN ANN ANA (α3) N AA ^(GIR 0AA|[A-PR-UWYZ]([A-HK-Y]([0-9][AZ]?|[1-9][0-9])|[1-9]([0-9]|[A-HJKPSTUW])?) [0-9][ABD-HJLNP-UW-Z]{2})$ 

Todos os códigos postais no jogo doogal.co.uk , exceto aqueles que não estão mais em uso.

Adicionando um ? depois do espaço e usando correspondência insensível a maiúsculas e minúsculas para responder a essa pergunta:

 'se50eg'.match(/^(GIR 0AA|[A-PR-UWYZ]([A-HK-Y]([0-9][AZ]?|[1-9][0-9])|[1-9]([0-9]|[A-HJKPSTUW])?) ?[0-9][ABD-HJLNP-UW-Z]{2})$/ig); Array [ "se50eg" ] 

Eu uso o seguinte regex que eu testei contra todos os códigos postais válidos no Reino Unido. Baseia-se nas regras recomendadas, mas se condensou tanto quanto razoável e não faz uso de nenhuma regra de regex específica do idioma.

 ([A-PR-UWYZ]([A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y])?|[0-9]([0-9]|[A-HJKPSTUW])?) ?[0-9][ABD-HJLNP-UW-Z]{2}) 

Assume-se que o código postal foi convertido em maiúsculas e não possui caracteres iniciais ou finais, mas aceitará um espaço opcional entre o código externo e o código.

O código postal especial “GIR0 0AA” foi excluído e não será validado, pois não está na lista oficial de códigos postais dos Correios e, até onde eu saiba, não será usado como endereço registrado. Adicioná-lo deve ser trivial como um caso especial, se necessário.

Este permite espaços vazios e guias de ambos os lados, caso você não queira falhar na validação e, em seguida, cortar o lado do servidor.

 ^\s*(([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,1}[0-9][A-Za-z]{2})\s*$) 

aqui está como estamos lidando com a questão do código postal do Reino Unido:

 ^([A-Za-z]{1,2}[0-9]{1,2}[A-Za-z]?[ ]?)([0-9]{1}[A-Za-z]{2})$ 

Explicação:

  • esperar 1 ou 2 caracteres az, multa superior ou inferior
  • espere 1 ou 2 números
  • esperar 0 ou 1 az car, superior ou inferior multa
  • espaço opcional permitido
  • espere 1 número
  • esperar 2 az, multa superior ou inferior

Isso obtém a maioria dos formatos e, em seguida, usamos o database para validar se o código postal é realmente real. Esses dados são orientados pelo ponto aberto https://www.ordnancesurvey.co.uk/opendatadownload/products.html

espero que isto ajude

Para adicionar a esta lista, um regex mais prático que eu uso e que permite ao usuário inserir uma empty string é:

 ^$|^(([gG][iI][rR] {0,}0[aA]{2})|((([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y]?[0-9][0-9]?)|(([a-pr-uwyzA-PR-UWYZ][0-9][a-hjkstuwA-HJKSTUW])|([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y][0-9][abehmnprv-yABEHMNPRV-Y]))) {0,1}[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2}))$ 

Esta regex permite letras maiúsculas e minúsculas com um espaço opcional entre

Do ponto de vista de um desenvolvedor de software, esse regex é útil para software em que um endereço pode ser opcional. Por exemplo, se um usuário não quisesse fornecer seus detalhes de endereço

Eu queria um regex simples, onde é bom permitir muito, mas não negar um código postal válido. Eu fui com isso (a input é uma string despojada / aparada):

/^([a-z0-9]\s*){5,7}$/i

Lengths 5 to 7 (not counting whitespace) means we allow the shortest possible postcodes like “L1 8JQ” as well as the longest ones like “OL14 5ET”.

EDIT: Changed the 8 to a 7 so we don’t allow 8 character postcodes.

Have a look at the python code on this page:

http://www.brunningonline.net/simon/blog/archives/001292.html

I’ve got some postcode parsing to do. The requirement is pretty simple; I have to parse a postcode into an outcode and (optional) incode. The good new is that I don’t have to perform any validation – I just have to chop up what I’ve been provided with in a vaguely intelligent manner. I can’t assume much about my import in terms of formatting, ie case and embedded spaces. But this isn’t the bad news; the bad news is that I have to do it all in RPG. 🙁

Nevertheless, I threw a little Python function together to clarify my thinking.

I’ve used it to process postcodes for me.

We were given a spec:

 UK postcodes must be in one of the following forms (with one exception, see below): 
    § A9 9AA 
    § A99 9AA
    § AA9 9AA
    § AA99 9AA
    § A9A 9AA
    § AA9A 9AA
where A represents an alphabetic character and 9 represents a numeric character.
Additional rules apply to alphabetic characters, as follows:
    § The character in position 1 may not be Q, V or X
    § The character in position 2 may not be I, J or Z
    § The character in position 3 may not be I, L, M, N, O, P, Q, R, V, X, Y or Z
    § The character in position 4 may not be C, D, F, G, I, J, K, L, O, Q, S, T, U or Z
    § The characters in the rightmost two positions may not be C, I, K, M, O or V
The one exception that does not follow these general rules is the postcode "GIR 0AA", which is a special valid postcode. 

We came up with this:

 /^([A-PR-UWYZ][A-HK-Y0-9](?:[A-HJKS-UW0-9][ABEHMNPRV-Y0-9]?)?\s*[0-9][ABD-HJLNP-UW-Z]{2}|GIR\s*0AA)$/i 

But note – this allows any number of spaces in between groups.

I have the regex for UK Postcode validation.

This is working for all type of Postcode either inner or outer

 ^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))) || ^((GIR)[ ]?(0AA))$|^(([A-PR-UWYZ][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][0-9][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][A-HK-Y0-9][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][A-HK-Y0-9][0-9][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][0-9][A-HJKS-UW0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][A-HK-Y0-9][0-9][ABEHMNPRVWXY0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$ 

This is working for all type of format.

Exemplo:

AB10——————–>ONLY OUTER POSTCODE

A1 1AA——————>COMBINATION OF (OUTER AND INNER) POSTCODE

WC2A——————–>OUTER

The accepted answer reflects the rules given by Royal Mail, although there is a typo in the regex. This typo seems to have been in there on the gov.uk site as well (as it is in the XML archive page).

In the format A9A 9AA the rules allow a P character in the third position, whilst the regex disallows this. The correct regex would be:

 (GIR 0AA)|((([AZ-[QVX]][0-9][0-9]?)|(([AZ-[QVX]][AZ-[IJZ]][0-9][0-9]?)|(([AZ-[QVX]][0-9][A-HJKPSTUW])|([AZ-[QVX]][AZ-[IJZ]][0-9][ABEHMNPRVWXY])))) [0-9][AZ-[CIKMOV]]{2}) 

Shortening this results in the following regex (which uses Perl/Ruby syntax):

 (GIR 0AA)|([A-PR-UWYZ](([0-9]([0-9A-HJKPSTUW])?)|([A-HK-Y][0-9]([0-9ABEHMNPRVWXY])?))\s?[0-9][ABD-HJLNP-UW-Z]{2}) 

It also includes an optional space between the first and second block.

here you can find a few helpful links, depends on what language you are using:

http://www.ukpostcode.net/wiki/develop

What i have found in nearly all the variations and the regex from the bulk transfer pdf and what is on wikipedia site is this, specifically for the wikipedia regex is, there needs to be a ^ after the first |(vertical bar). I figured this out by testing for AA9A 9AA, because otherwise the format check for A9A 9AA will validate it. For Example checking for EC1D 1BB which should be invalid comes back valid because C1D 1BB is a valid format.

Here is what I’ve come up with for a good regex:

 ^([G][I][R] 0[A]{2})|^((([AZ-[QVX]][0-9]{1,2})|([AZ-[QVX]][A-HK-Y][0-9]{1,2})|([AZ-[QVX]][0-9][ABCDEFGHJKPSTUW])|([AZ-[QVX]][A-HK-Y][0-9][ABEHMNPRVWXY])) [0-9][AZ-[CIKMOV]]{2})$ 

I recently posted an answer to this question on UK postcodes for the R language . I discovered that the UK Government’s regex pattern is incorrect and fails to properly validate some postcodes. Unfortunately, many of the answers here are based on this incorrect pattern.

I’ll outline some of these issues below and provide a revised regular expression that actually works.


Nota

My answer (and regular expressions in general):

  • Only validates postcode formats .
  • Does not ensure that a postcode legitimately exists .
    • For this, use an appropriate API! See Ben’s answer for more info.

The Bad Regex

The regular expressions in this section should not be used.

This is the failing regex that the UK government has provided developers (not sure how long this link will be up, but you can see it in their Bulk Data Transfer documentation ):

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

Problemas

Problem 1 – Copy/Paste

See regex in use here .

As many developers likely do, they copy/paste code (especially regular expressions) and paste them expecting them to work. While this is great in theory, it fails in this particular case because copy/pasting from this document actually changes one of the characters (a space) into a newline character as shown below:

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

The first thing most developers will do is just erase the newline without thinking twice. Now the regex won’t match postcodes with spaces in them (other than the GIR 0AA postcode).

To fix this issue, the newline character should be replaced with the space character:

 ^([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 – Boundaries

See regex in use here .

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

The postcode regex improperly anchors the regex. Anyone using this regex to validate postcodes might be surprised if a value like fooA11 1AA gets through. That’s because they’ve anchored the start of the first option and the end of the second option (independently of one another), as pointed out in the regex above.

What this means is that ^ (asserts position at start of the line) only works on the first option ([Gg][Ii][Rr] 0[Aa]{2}) , so the second option will validate any strings that end in a postcode (regardless of what comes before).

Similarly, the first option isn’t anchored to the end of the line $ , so GIR 0AAfoo is also accepted.

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

To fix this issue, both options should be wrapped in another group (or non-capturing group) and the anchors placed around that:

 ^(([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 3 – Improper Character Set

See regex in use here .

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

The regex is missing a - here to indicate a range of characters. As it stands, if a postcode is in the format ANA NAA (where A represents a letter and N represents a number), and it begins with anything other than A or Z , it will fail.

That means it will match A1A 1AA and Z1A 1AA , but not B1A 1AA .

To fix this issue, the character - should be placed between the A and Z in the respective character set:

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

Problem 4 – Wrong Optional Character Set

See regex in use here .

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

I swear they didn’t even test this thing before publicizing it on the web. They made the wrong character set optional. They made [0-9] option in the fourth sub-option of option 2 (group 9). This allows the regex to match incorrectly formatted postcodes like AAA 1AA .

To fix this issue, make the next character class optional instead (and subsequently make the set [0-9] match exactly once):

 ^([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 5 – Performance

Performance on this regex is extremely poor. First off, they placed the least likely pattern option to match GIR 0AA at the beginning. How many users will likely have this postcode versus any other postcode; probably never? This means every time the regex is used, it must exhaust this option first before proceeding to the next option. To see how performance is impacted check the number of steps the original regex took (35) against the same regex after having flipped the options (22).

The second issue with performance is due to the way the entire regex is structured. There’s no point backtracking over each option if one fails. The way the current regex is structured can greatly be simplified. I provide a fix for this in the Answer section.

Problem 6 – Spaces

See regex in use here

This may not be considered a problem , per se, but it does raise concern for most developers. The spaces in the regex are not optional, which means the users inputting their postcodes must place a space in the postcode. This is an easy fix by simply adding ? after the spaces to render them optional. See the Answer section for a fix.


Responda

1. Fixing the UK Government’s Regex

Fixing all the issues outlined in the Problems section and simplifying the pattern yields the following, shorter, more concise pattern. We can also remove most of the groups since we’re validating the postcode as a whole (not individual parts):

See regex in use here

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

This can further be shortened by removing all of the ranges from one of the cases (upper or lower case) and using a case-insensitive flag. Note : Some languages don’t have one, so use the longer one above. Each language implements the case-insensitivity flag differently.

See regex in use here .

 ^([AZ][A-HJ-Y]?[0-9][A-Z0-9]? ?[0-9][AZ]{2}|GIR ?0A{2})$ 

Shorter again replacing [0-9] with \d (if your regex engine supports it):

See regex in use here .

 ^([AZ][A-HJ-Y]?\d[AZ\d]? ?\d[AZ]{2}|GIR ?0A{2})$ 

2. Simplified Patterns

Without ensuring specific alphabetic characters, the following can be used (keep in mind the simplifications from 1. Fixing the UK Government’s Regex have also been applied here):

See regex in use here .

 ^([AZ]{1,2}\d[AZ\d]? ?\d[AZ]{2}|GIR ?0A{2})$ 

And even further if you don’t care about the special case GIR 0AA :

 ^[AZ]{1,2}\d[AZ\d]? ?\d[AZ]{2}$ 

3. Complicated Patterns

I would not suggest over-verification of a postcode as new Areas, Districts and Sub-districts may appear at any point in time. What I will suggest potentially doing, is added support for edge-cases. Some special cases exist and are outlined in this Wikipedia article .

Here are complex regexes that include the subsections of 3.

In relation to the patterns in 1. Fixing the UK Government’s Regex :

See regex in use here

 ^(([AZ][A-HJ-Y]?\d[AZ\d]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?\d[AZ]{2}|BFPO ?\d{1,4}|(KY\d|MSR|VG|AI)[ -]?\d{4}|[AZ]{2} ?\d{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$ 

And in relation to 2. Simplified Patterns :

See regex in use here

 ^(([AZ]{1,2}\d[AZ\d]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?\d[AZ]{2}|BFPO ?\d{1,4}|(KY\d|MSR|VG|AI)[ -]?\d{4}|[AZ]{2} ?\d{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$ 

3.1 British Overseas Territories

The Wikipedia article currently states (some formats slightly simplified):

  • AI-1111 : Anguila
  • ASCN 1ZZ : Ascension Island
  • STHL 1ZZ : Saint Helena
  • TDCU 1ZZ : Tristan da Cunha
  • BBND 1ZZ : British Indian Ocean Territory
  • BIQQ 1ZZ : British Antarctic Territory
  • FIQQ 1ZZ : Falkland Islands
  • GX11 1ZZ : Gibraltar
  • PCRN 1ZZ : Pitcairn Islands
  • SIQQ 1ZZ : South Georgia and the South Sandwich Islands
  • TKCA 1ZZ : Turks and Caicos Islands
  • BFPO 11 : Akrotiri and Dhekelia
  • ZZ 11 & GE CX : Bermuda (according to this document )
  • KY1-1111 : Cayman Islands (according to this document )
  • VG1111 : British Virgin Islands (according to this document )
  • MSR 1111 : Montserrat (according to this document )

An all-encompassing regex to match only the British Overseas Territories might look like this:

See regex in use here .

 ^((ASCN|STHL|TDCU|BBND|[BFS]IQQ|GX\d{2}|PCRN|TKCA) ?\d[AZ]{2}|(KY\d|MSR|VG|AI)[ -]?\d{4}|(BFPO|[AZ]{2}) ?\d{2}|GE ?CX)$ 

3.2 British Forces Post Office

Although they’ve been recently changed it to better align with the British postcode system to BF# (where # represents a number), they’re considered optional alternative postcodes . These postcodes follow(ed) the format of BFPO , followed by 1-4 digits:

See regex in use here

 ^BFPO ?\d{1,4}$ 

3.3 Santa?

There’s another special case with Santa (as mentioned in other answers): SAN TA1 is a valid postcode. A regex for this is very simply:

 ^SAN ?TA1$ 

I needed a version that would work in SAS with the PRXMATCH and related functions, so I came up with this:

 ^[A-PR-UWYZ](([A-HK-Y]?\d\d?)|(\d[A-HJKPSTUW])|([A-HK-Y]\d[ABEHMNPRV-Y]))\s?\d[ABD-HJLNP-UW-Z]{2}$ 

Test cases and notes:

 /* Notes The letters QVX are not used in the 1st position. The letters IJZ are not used in the second position. The only letters to appear in the third position are ABCDEFGHJKPSTUW when the structure starts with A9A. The only letters to appear in the fourth position are ABEHMNPRVWXY when the structure starts with AA9A. The final two letters do not use the letters CIKMOV, so as not to resemble digits or each other when hand-written. */ /* Bits and pieces 1st position (any): [A-PR-UWYZ] 2nd position (if letter): [A-HK-Y] 3rd position (A1A format): [A-HJKPSTUW] 4th position (AA1A format): [ABEHMNPRV-Y] Last 2 positions: [ABD-HJLNP-UW-Z] */ data example; infile cards truncover; input valid 1. postcode &$10. Notes &$100.; flag = prxmatch('/^[A-PR-UWYZ](([A-HK-Y]?\d\d?)|(\d[A-HJKPSTUW])|([A-HK-Y]\d[ABEHMNPRV-Y]))\s?\d[ABD-HJLNP-UW-Z]{2}$/',strip(postcode)); cards; 1 EC1A 1BB Special case 1 1 W1A 0AX Special case 2 1 M1 1AE Standard format 1 B33 8TH Standard format 1 CR2 6XH Standard format 1 DN55 1PT Standard format 0 QN55 1PT Bad letter in 1st position 0 DI55 1PT Bad letter in 2nd position 0 W1Z 0AX Bad letter in 3rd position 0 EC1Z 1BB Bad letter in 4th position 0 DN55 1CT Bad letter in 2nd group 0 A11A 1AA Invalid digits in 1st group 0 AA11A 1AA 1st group too long 0 AA11 1AAA 2nd group too long 0 AA11 1AAA 2nd group too long 0 AAA 1AA No digit in 1st group 0 AA 1AA No digit in 1st group 0 A 1AA No digit in 1st group 0 1A 1AA Missing letter in 1st group 0 1 1AA Missing letter in 1st group 0 11 1AA Missing letter in 1st group 0 AA1 1A Missing letter in 2nd group 0 AA1 1 Missing letter in 2nd group ; run;