Search code examples
phpregexpostal-code

Validate UK Postcode - both short and long version


I have tried the one on the .gov website, as stated on many questions here, but it doesnt seem to work for short postcodes.

My regex:

preg_match('^(([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}))^', $this->post['location'], $matches)

When I use a long postcode of format: AA9 9ZZ it works, but one of format AA9 doesnt. I need the following formats to work:

  • AA9
  • AA99
  • AA9 9ZZ
  • AA99 9ZZ

Solution

  • According to the pattern you have given and making the second part optional, I obtain:

    ~^(?:gir(?: *0aa)?|[a-pr-uwyz](?:[a-hk-y]?[0-9]+|[0-9][a-hjkstuw]|[a-hk-y][0-9][abehmnprv-y])(?: *[0-9][abd-hjlnp-uw-z]{2})?)$~i
    

    demo

    or to make it more readable:

    ~ # pattern delimiter
    ^ # start of the string anchor
    (?: # branch 1
        gir
        (?:[ ]*0aa)? # second part optional (branch 1)
      | # branch 2
        [a-pr-uwyz] # I put it in factor to shorten the pattern
        (?:
            [a-hk-y]?[0-9]+
          |
            [0-9][a-hjkstuw]
          |
            [a-hk-y][0-9][abehmnprv-y]
        )
        (?:[ ]*[0-9][abd-hjlnp-uw-z]{2})? # second part optional (branch 2)
    )
    $ # end of the string anchor
    ~ix