2

I need a regex to match the first half of a uk postcode, and it's possible just one half or a full post code could get passed in.

There is great way to match full postcode here: UK Postcode Regex (Comprehensive)

However I need to just get the first 3 or 4 characters of a postcode, with the possibility of half a post code or a postcode without spaces getting passed in, so any of these:

SL4 4BZ
SL44BZ - this will pull out just 'SL4'
SL4
DY10
DY10 3BD
DY10 3BD

The regex needs to match:

  • if it's 5 characters long (excluding spaces), remove last 3 characters and the first 2 remaining characters are the half-a-postcode
  • if it's 6 characters long (excluding spaces), remove last 3 characters and the first 3 remaining characters are the half-a-postcode
  • if it's 7 characters long (excluding spaces), remove last 3 characters and the first 4 remaining characters are the half-a-postcode
  • if it's 2, 3 or 4 characters long, keep it

But I can't quite get my head around how to write something this complex.

Community
  • 1
  • 1
CafeHey
  • 5,699
  • 19
  • 82
  • 145
  • Spaces ? They seem significant when writing a pattern, they don't count do they ? What about `SL 44BZT` ? –  Oct 21 '14 at 18:11
  • Do you _have_ to do this with a regex? What you've described would be dead easy using string manipulation. – arco444 Oct 21 '14 at 18:13
  • You actually have to use some method to distinquish between 3 or 4 postcode, other than length or spaces. –  Oct 21 '14 at 18:15
  • 1
    http://stackoverflow.com/questions/21616133/how-to-correctly-match-uk-postcodes-by-prefix/21626470#21626470 – Al Mills Oct 21 '14 at 18:29

2 Answers2

2

Updated for 2/5 characters as well, total coverage = 2/5 or 3/6 or 4/7

This works for the input samples.
Here are 2 variations of the same thing.

Results in Capture group 1

 #  (?m)^([A-Z0-9]{2,4})(?:\s*[A-Z0-9]{3})?$

 (?m)
 ^ 
 (                             # (1 start)
      [A-Z0-9]{2,4} 
 )                             # (1 end)
 (?: \s* [A-Z0-9]{3} )?
 $ 

Results in Capture group 0

 # (?m)^[A-Z0-9]{2,4}(?=(?:\s*[A-Z0-9]{3})?$)

 (?m)
 ^ 
 [A-Z0-9]{2,4} 
 (?=
      (?: \s* [A-Z0-9]{3} )?
      $ 
 )

@Smickie - Update - Regarding your question about inline-modifiers in JS.
(I'm not a JS expert but here is a simple example)
I don't believe inline modifiers construct are available. However, they can be added
via the flags parameter (enum) or in the /../flags notation.

You can see this example work in JSfiddle here --> http://jsfiddle.net/cdcv8uug/

var teststr = "SL\nSL 4BZ\nSL4BZ\nSL4\nSL4 4BZ\nSL44BZ\nDY10\nDY10 3BD\nDY10 3BD";

var arr = teststr.match( /^[A-Z0-9]{2,4}(?=(?:\s*[A-Z0-9]{3})?$)/mg );

var res = "Using match() -> Capture group 0\nteststr.match(/^[A-Z0-9]{2,4}(?=(?:\s*[A-Z0-9]{3})?$)/mg)\n";
for (var index = 0; index < arr.length; index++)
{
   res += index + ":  " +  arr[index] + "\n";
}

var re = /^([A-Z0-9]{2,4})(?:\s*[A-Z0-9]{3})?$/mg;
res += "\nUsing exec() -> Capture group 1\nvar re = /^([A-Z0-9]{2,4})(?:\s*[A-Z0-9]{3})?$/mg;\nre.exec(teststr)\n";

index = 0;
while ((arr = re.exec(teststr)) != null)
{
    res += index + ":  " + arr[1] + "\n";
    index++;
}

alert( res );
  • This is fantastic but... the '(?m)' modifier doesn't work with JavaScript's match, is it possible to make it work with that? – CafeHey Oct 22 '14 at 11:51
  • @Smickie - Re: `This is fantastic but... the '(?m)' modifier doesn't work with JavaScript's match, is it possible to make it work with that? – Smickie 4 hours ago` Added an update. –  Oct 22 '14 at 16:42
0

Assuming the postcode represents the entire string, try

^[A-Z0-9]{3}([A-Z0-9](?=\s*[A-Z0-9]{3}|$))?

You may want to set the case-insensitive option, and you should set ^$ match at linebreaks

The regex matches the first three letters or digits, and then matches a fourth character if it is followed by three more characters, or by the end of the line.

If you want to try to also validate the post code fragment, the regex would be more complex. And would need to be updated frequently -- Wikipedia indicates that every month 2,750 new codes are created and 2,500 are terminated. I imagine some of the rules change also.

Ron Rosenfeld
  • 53,870
  • 7
  • 28
  • 60