UK Postcode Regex (Completo)

Estoy buscando una expresión regular que valide un código postal completo de UK solo dentro de una cadena de entrada. Todos los formularios de código postal poco comunes deben ser cubiertos tan bien como los habituales. Por ejemplo:

Partidos

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

Sin coincidencia

  • aWC2H 7LT
  • WC2H 7LTa
  • WC2H

¿Hay expresiones regulares oficiales o incluso semioficiales en uso para este tipo de cosas? ¿Algún otro consejo sobre cómo formatear y almacenar estos en una base de datos?

Recomiendo echar un vistazo al estándar de datos del gobierno del Reino Unido para los códigos postales [link now dead; archivo de XML , ver Wikipedia para discusión]. Hay una breve descripción de los datos y el esquema xml adjunto proporciona una expresión regular. Puede que no sea exactamente lo que quieres, pero sería un buen punto de partida. El RegEx difiere ligeramente del XML, ya que la definición dada permite un carácter P en la tercera posición en el formato A9A 9AA.

El RegEx suministrado por el gobierno del Reino Unido fue:

([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 se señaló en la discusión de Wikipedia, esto permitirá algunos códigos postales no reales (por ejemplo, los que comienzan con AA, ZY) y proporcionan una prueba más rigurosa que podría intentar.

Parece que vamos a 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 es una versión ligeramente modificada de eso sugerido por Minglis arriba.

Sin embargo, vamos a tener que investigar exactamente cuáles son las reglas, ya que las diversas soluciones enumeradas anteriormente parecen aplicar reglas diferentes sobre qué letras están permitidas.

Después de algunas investigaciones, hemos encontrado más información. Al parecer, una página en ‘govtalk.gov.uk’ te dirige a una especificación de código postal govtalk-postcodes . Esto apunta a un esquema XML en XML Schema que proporciona una statement ‘pseudo regex’ de las reglas de código postal.

Tomamos eso y trabajamos un poco para darnos la siguiente expresión:

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

Esto hace que los espacios sean opcionales, pero te limita a un espacio (reemplaza el ‘&’ por ‘{0,} para espacios ilimitados). Se supone que todo el texto debe estar en mayúscula.

Si desea permitir minúsculas, con cualquier cantidad de espacios, 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}))$ 

Esto no cubre los territorios de ulttwigr y solo aplica el formato, NO la existencia de diferentes áreas. Se basa en las siguientes reglas:

Puede aceptar los siguientes formatos:

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

Dónde:

  • 9 puede ser cualquier número de un solo dígito.
  • A puede ser cualquier letra excepto Q, V o X.
  • B puede ser cualquier letra excepto I, J o Z.
  • C puede ser cualquier letra excepto I, L, M, N, O, P, Q, R, V, X, Y o Z.
  • D puede ser cualquier letra excepto I, J o Z.
  • E puede ser cualquiera de A, B, E, H, M, N, P, R, V, W, X o Y.
  • Z puede ser cualquier letra excepto C, I, K, M, O o V.

Los mejores deseos

Colin

No existe una expresión regular completa del código postal del Reino Unido que sea capaz de validar un código postal. Puede verificar que un código postal esté en el formato correcto usando una expresión regular; no es que realmente exista.

Los códigos postales son arbitrariamente complejos y cambian constantemente. Por ejemplo, el código de salida W1 no tiene, y puede que nunca tenga, cada número entre 1 y 99, para cada área de código postal.

No puede esperar que lo que hay actualmente sea cierto para siempre. Como ejemplo, en 1990, la Oficina de Correos decidió que Aberdeen estaba un poco abarrotada. Agregaron un 0 al final de AB1-5 por lo que es AB10-50 y luego crearon una serie de códigos postales entre estos.

Cada vez que se construye una nueva calle, se crea un nuevo código postal. Es parte del proceso para obtener permiso para construir; las autoridades locales están obligadas a mantener esto actualizado con la Oficina de Correos (no es que todos lo hagan).

Además, como notaron otros usuarios, están los códigos postales especiales, como Girobank, GIR 0AA, y el de las cartas a Santa, SAN TA1, probablemente no quieras publicar nada allí, pero no parece estar cubierto por cualquier otra respuesta.

Luego, están los códigos postales de BFPO, que ahora están cambiando a un formato más estándar . Ambos formatos van a ser válidos. Por último, está la fuente de los territorios de ulttwigr Wikipedia .

 + ---------- + -------------------------------------- -------- +
 |  Código postal |  Ubicación |
 + ---------- + -------------------------------------- -------- +
 |  AI-2640 |  Anguila |
 |  ASCN 1ZZ |  Isla Ascensión |
 |  STHL 1ZZ |  Santa Helena |
 |  TDCU 1ZZ |  Tristan da Cunha |
 |  BBND 1ZZ |  Territorio Británico del Océano Índico |
 |  BIQQ 1ZZ |  Territorio Antártico Británico |
 |  FIQQ 1ZZ |  Islas Malvinas |
 |  GX11 1AA |  Gibraltar |
 |  PCRN 1ZZ |  Islas Pitcairn |
 |  SIQQ 1ZZ |  Islas Georgias del Sur y Sandwich del Sur |
 |  TKCA 1ZZ |  Islas Turcas y Caicos |
 + ---------- + -------------------------------------- -------- + 

Luego, debe tener en cuenta que el Reino Unido “exportó” su sistema de código postal a muchos lugares del mundo. Cualquier cosa que valide un código postal “UK” también validará los códigos postales de varios otros países.

Si desea validar un código postal del Reino Unido, la forma más segura de hacerlo es utilizar una búsqueda de los códigos postales actuales. Hay muchas opciones:

  • Ordnance Survey lanza Code-Point Open bajo una licencia de datos abiertos. Estará un poco retrasado pero es gratis. Esto (probablemente, no recuerdo) no incluirá los datos de Irlanda del Norte, ya que la Encuesta de Artillería no tiene ninguna competencia allí. El mapeo en Irlanda del Norte se lleva a cabo por el Ordnance Survey de Irlanda del Norte y tienen su producto Pointer separado, pagado. Puede usar esto y anexar los pocos que no están cubiertos con bastante facilidad.

  • Royal Mail publica el archivo de dirección de código postal (PAF) , esto incluye BFPO, que no estoy seguro de que Code-Point Open sí. Se actualiza regularmente pero cuesta dinero (y pueden ser francamente malos al respecto a veces). PAF incluye la dirección completa en lugar de solo los códigos postales y viene con su propia Guía de progtwigdores . El Grupo de Usuarios de Datos Abiertos (ODUG, por sus siglas en inglés) actualmente está presionando para que se libere el PAF de forma gratuita, aquí hay una descripción de su posición .

  • Por último, hay AddressBase . Esta es una colaboración entre Ordnance Survey, Autoridades Locales, Royal Mail y una compañía que combina para crear un directorio definitivo de toda la información sobre todas las direcciones del Reino Unido (también han sido bastante exitosas). Se paga, pero si trabaja con una autoridad local, un departamento gubernamental o un servicio del gobierno, es gratis para ellos. Hay mucha más información que solo los códigos postales incluidos.

Eché un vistazo a algunas de las respuestas anteriores y recomendaría no utilizar el patrón de la respuesta de @ Dan (c. 15 de diciembre de 2010 ) , ya que indica incorrectamente casi el 0,4% de los códigos postales válidos como no válidos, mientras que los otros no .

Ordnance Survey proporciona un servicio llamado Code Point Open que:

contiene una lista de todas las unidades actuales de código postal en Gran Bretaña

Ejecuté cada una de las expresiones regulares anteriores en la lista completa de códigos postales (6 de julio de 2013) a partir de estos datos usando 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" 

Hay 1,686,202 códigos postales en total.

Los siguientes son los números de códigos postales válidos que no coinciden con 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 

Por supuesto, estos resultados solo se ocupan de los códigos postales válidos que se marcan incorrectamente como no válidos. Asi que:

 '^.*$' # => 0 

No digo nada sobre qué patrón es el mejor para filtrar los códigos postales no válidos.

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

Expresión regular para coincidir con los códigos postales válidos del Reino Unido. En el sistema postal del Reino Unido, no todas las letras se usan en todas las posiciones (lo mismo con las placas de matrícula del vehículo) y existen varias reglas para regular esto. Esta expresión regular tiene en cuenta esas reglas. Detalles de las reglas: Primera mitad del 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] Excepciones Posición – Primero. Contraint – QVX no utilizado Posición – Segundo. Contraint – IJZ no utilizado excepto en la posición GIR 0AA – Tercero. Restricción – AEHMNPRTVXY solo utilizó Posición – Adelante. Contraint – ABEHMNPRVWXY Segunda mitad del código postal Formatos válidos [0-9] [AZ] [AZ] Excepciones Posición – Segundo y tercero. Contraint – CIKMOV no utilizado

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

Una publicación anterior pero todavía bastante alta en los resultados de Google, así que pensé en actualizarla. Este documento del 14 de octubre define la expresión regular del código postal del 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})$ 

de:

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

El documento también explica la lógica detrás de esto. Sin embargo, tiene un error (en negrita) y también permite minúsculas, que aunque legales no son habituales, la versión modificada:

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

Esto funciona con los nuevos códigos postales de Londres (por ejemplo, W1D 5LH) que las versiones anteriores no.

La mayoría de las respuestas aquí no funcionaron para todos los códigos postales que tengo en mi base de datos. Finalmente encontré uno que valida con todos, usando la nueva expresión regular proporcionada por el gobierno:

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

No está en ninguna de las respuestas anteriores, así que lo publico aquí en caso de que eliminen el enlace:

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

ACTUALIZACIÓN: regex actualizada según lo señaló Jamie Bull. No estoy seguro si fue un error al copiar o si fue un error en la expresión regular del gobierno, ahora el enlace está inactivo …

ACTUALIZACIÓN: Como se encontró ctwheels, esta expresión regular funciona con el sabor javascript regex. Vea su comentario para uno que funcione con el sabor pcre (php).

De acuerdo con esta tabla de Wikipedia

enter image description here

Este patrón cubre todos los 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}) 

Al usarlo en Android \ Java use \\ d

Los códigos postales están sujetos a cambios, y la única forma verdadera de validar un código postal es tener la lista completa de códigos postales y ver si están allí.

Pero las expresiones regulares son útiles porque:

  • son fáciles de usar e implementar
  • son cortos
  • son rápidos de ejecutar
  • son bastante fáciles de mantener (en comparación con una lista completa de códigos postales)
  • Todavía captura la mayoría de los errores de entrada

Pero las expresiones regulares tienden a ser difíciles de mantener, especialmente para alguien que no se le ocurrió en primer lugar. Entonces debe ser:

  • tan fácil de entender como sea posible
  • relativamente a prueba de futuro

Eso significa que la mayoría de las expresiones regulares en esta respuesta no son lo suficientemente buenas. Por ejemplo, puedo ver que [A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y] va a coincidir con un área de código postal de la forma AA1A, pero va a ser un dolor en el cuello si y cuando se agrega un nuevo área de código postal, porque es difícil entender qué áreas de código postal coincide.

También quiero que mi expresión regular coincida con la primera y la segunda mitad del código postal como coincidencias entre paréntesis.

Así que se me ocurrió esto:

 (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}) 

En formato PCRE, se puede escribir de la siguiente manera:

 /^ ( 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 mí, este es el equilibrio correcto entre la validación tanto como sea posible y, al mismo tiempo, a prueba de futuro y que permita un mantenimiento sencillo.

He estado buscando una expresión regular de código postal del Reino Unido durante el último día y tropecé con este hilo. Trabajé para la mayoría de las sugerencias anteriores y ninguna de ellas me funcionó, así que ideé mi propia expresión regular que, hasta donde sé, captura todos los códigos postales válidos del Reino Unido a partir de enero de 2013 (según la última literatura de el Correo Real).

La expresión regular y algunos códigos postales simples que verifican el código PHP se publican a continuación. NOTA: – Permite códigos postales más bajos o mayúsculos y la anomalía GIR 0AA, pero para tratar con la presencia, más que probable, de un espacio en el medio de un código postal introducido, también hace uso de un str_replace simple para eliminar el espacio antes de la prueba contra la expresión regular. Cualquier discrepancia más allá de eso y el Royal Mail ni siquiera los menciona en su literatura (ver http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf y comienza a leer en la página 17) !

Nota: En la propia literatura del Royal Mail (enlace arriba) existe una leve ambigüedad en torno a la tercera y cuarta posiciones y las excepciones vigentes si estos caracteres son letras. Me puse en contacto con Royal Mail directamente para aclararlo y con sus propias palabras: “Una carta en la 4ª posición del Código de salida con el formato AANA NAA no tiene excepciones y las excepciones de la 3ª posición se aplican solo a la última letra del Código de salida con el formato ANA NAA “. ¡Directo de la boca del caballo!

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

Espero que ayude a cualquier otra persona que encuentre este hilo en busca de una solución.

Esta es la expresión regular que Google publica en su dominio 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} 

Aquí hay una expresión regular basada en el formato especificado en los documentos que están vinculados a la respuesta de marcj:

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

La única diferencia entre eso y las especificaciones es que los últimos 2 caracteres no pueden estar en [CIKMOV] de acuerdo con las especificaciones.

Editar: Aquí hay otra versión que prueba las limitaciones del carácter final.

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

Algunas de las expresiones regulares anteriores son un poco restrictivas. Tenga en cuenta que el código postal genuino: “W1K 7AA” fallaría dado que la regla “Posición 3 – AEHMNPRTVXY solo se utilizaba” arriba ya que “K” no se permitiría.

la expresión regular:

 ^(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 un poco más preciso, ver el artículo de Wikipedia titulado ‘Códigos postales en el Reino Unido’ .

Tenga en cuenta que esta expresión regular requiere mayúsculas solo caracteres.

La pregunta más importante es si está restringiendo la entrada del usuario para permitir solo los códigos postales que realmente existen o si simplemente está tratando de evitar que los usuarios ingresen basura completa en los campos del formulario. Corregir correctamente todos los códigos postales posibles y probarlos en el futuro es un acertijo más difícil, y probablemente no valga la pena a menos que seas HMRC.

Reglas básicas:

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

Los códigos postales en el Reino Unido (o los códigos postales, como se los llama) se componen de cinco a siete caracteres alfanuméricos separados por un espacio. Las reglas que cubren qué personajes pueden aparecer en posiciones particulares son bastante complicadas y plagadas de excepciones. La expresión regular que se acaba de mostrar se atiene a las reglas básicas.

Reglas completas:

Si necesita una expresión regular que marque todos los cuadros de las reglas del código postal a expensas de la legibilidad, aquí tiene:

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

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

Probado en nuestra base de datos de clientes y parece perfectamente exacto.

Primera mitad del 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]

Excepciones
Posición 1 – QVX no utilizado
Posición 2 – IJZ no utilizado excepto en GIR 0AA
Posición 3: solo AEHMNPRTVXY se usó
Posición 4 – ABEHMNPRVWXY

La segunda mitad del código postal

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

Excepciones
Posición 2 + 3 – CIKMOV no utilizado

Recuerde que no se utilizan todos los códigos posibles, por lo que esta lista es una condición necesaria pero no suficiente para un código válido. ¿Podría ser más fácil simplemente coincidir con una lista de todos los códigos válidos?

Para verificar que un código postal esté en un formato válido según la guía del progtwigdor del 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 los códigos postales coinciden en doogal.co.uk , excepto los que ya no se usan.

Agregar un ? después del espacio y usando la concordancia de mayúsculas y minúsculas para responder esta pregunta:

 '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" ] 

Utilizo la siguiente expresión regular que he probado contra todos los códigos postales válidos del Reino Unido. Se basa en las reglas recomendadas, pero se condensa tanto como sea razonable y no hace uso de ninguna regla especial de expresiones regulares específicas del 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}) 

Supone que el código postal se ha convertido a mayúsculas y no tiene caracteres iniciales o finales, pero aceptará un espacio opcional entre el código de salida y el código de entrada.

El código especial “GIR0 0AA” está excluido y no se validará ya que no está en la lista oficial de códigos postales de la Oficina Postal y, por lo que sé, no se usará como dirección registrada. Agregarlo debería ser trivial como un caso especial si es necesario.

Este permite espacios vacíos y tabs de ambos lados en caso de que no quiera fallar la validación y luego recortarlo del lado del 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*$) 

así es como hemos estado lidiando con el problema del código postal del Reino Unido:

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

Explicación:

  • espere 1 o 2 az caracteres, multa superior o inferior
  • espera 1 o 2 números
  • esperar 0 o 1 az char, multa superior o inferior
  • espacio opcional permitido
  • esperar 1 numero
  • esperar 2 az, multa superior o inferior

Esto obtiene la mayoría de los formatos, luego usamos el db para validar si el código postal es realmente real, esta información es manejada por el punto abierto https://www.ordnancesurvey.co.uk/opendatadownload/products.html

espero que esto ayude

Para agregar a esta lista una expresión regular más práctica que uso que permite al usuario ingresar una empty string es:

 ^$|^(([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 expresión regular permite mayúsculas y minúsculas con un espacio opcional entre ellas

Desde el punto de vista de los desarrolladores de software, esta expresión regular es útil para el software donde una dirección puede ser opcional. Por ejemplo, si un usuario no desea proporcionar los detalles de su dirección

Quería una expresión regular simple, donde está bien permitir demasiado, pero no negar un código postal válido. Fui con esto (la entrada es una cadena stripped / trimmed):

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

Las longitudes de 5 a 7 (sin contar espacios en blanco) significa que permitimos los códigos postales más cortos posibles, como “L1 8JQ”, así como los más largos, como “OL14 5ET”.

EDITAR: Cambió el 8 a un 7, por lo que no permitimos códigos postales de 8 caracteres.

Eche un vistazo al código python en esta página:

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

Tengo que analizar algunos códigos postales. El requisito es bastante simple; Tengo que analizar un código postal en un outcode y (opcional) incode. Lo bueno es que no tengo que realizar ninguna validación, solo tengo que cortar lo que me han proporcionado de una manera vagamente inteligente. No puedo asumir mucho sobre mi importación en términos de formato, es decir, el caso y los espacios integrados. Pero esta no es la mala noticia; la mala noticia es que tengo que hacerlo todo en RPG. 🙁

Sin embargo, lancé una pequeña función de Python para aclarar mi pensamiento.

Lo he usado para procesar los códigos postales para mí.

Nos dieron una especificación:

  Los códigos postales del Reino Unido deben estar en uno de los siguientes formularios (con una excepción, ver a continuación): 
     § A9 9AA 
     § A99 9AA
     § AA9 9AA
     § AA99 9AA
     § A9A 9AA
     § AA9A 9AA
 donde A representa un carácter alfabético y 9 representa un carácter numérico.
 Se aplican reglas adicionales a los caracteres alfabéticos de la siguiente manera:
     § El personaje en la posición 1 puede no ser Q, V o X
     § El personaje en la posición 2 puede no ser I, J o Z
     § El personaje en la posición 3 puede no ser I, L, M, N, O, P, Q, R, V, X, Y o Z
     § El personaje en la posición 4 puede no ser C, D, F, G, I, J, K, L, O, Q, S, T, U o Z
     § Los personajes en las dos posiciones más a la derecha no pueden ser C, I, K, M, O o 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.

Ejemplo:

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.


Responder

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; 
Intereting Posts