140

Possible Duplicate:
What is the ultimate postal code and zip regex?

I need Regex which can satisfy all my three condtions for zip-code. E.g-

  1. 12345
  2. 12345-6789
  3. 12345 1234

Any pointers and suggestion would be much appreciated. Thanks !

Community
  • 1
  • 1
Shaitender Singh
  • 2,157
  • 5
  • 22
  • 35
  • 5
    The duplicate closure looks sketchy - the dupe is asking for a regex that will match any postal code from any nation ever, whereas this question is asking for a regex to match zip codes, which are a US-only thing, which makes this question much narrower in scope than the dupe - but there *is* in fact an answer to be found at the dupe. See https://stackoverflow.com/a/7185241/1709587 which lists the Unicode CLDR's (old, now deprecated, but probably still adequate in many cases) postal code regexes for >100 countries, including the US. The US regex is `\d{5}([ \-]\d{4})?`. – Mark Amery Oct 09 '18 at 14:29

3 Answers3

352
^\d{5}(?:[-\s]\d{4})?$
  • ^ = Start of the string.
  • \d{5} = Match 5 digits (for condition 1, 2, 3)
  • (?:…) = Grouping
  • [-\s] = Match a space (for condition 3) or a hyphen (for condition 2)
  • \d{4} = Match 4 digits (for condition 2, 3)
  • …? = The pattern before it is optional (for condition 1)
  • $ = End of the string.
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 8
    `\s` will match any whitespace, including tabs and new lines. – eyelidlessness Apr 05 '10 at 07:33
  • 2
    Hi what about the condition 123451234 without space – Ajay Suwalka Oct 10 '14 at 11:42
  • 5
    @ProVega: Reading the comments on the (now deleted) answer you linked to, that appears to be incorrect. For example, `00544` is a valid zip code; `544` is not. – Keith Thompson Dec 05 '14 at 20:59
  • 2
    @AjaySuwalka: All you would have to do to accommodate for 123451234 with no space is place a ? after [-\s], so it would become: ^\d{5}(?:[-\s]?\d{4})?$ – Grungondola Oct 16 '15 at 17:04
  • in Javascript I put it this way: var zipPattern = /\d{5}(?:[-]\d{4})?/; if (!zipPattern.test($scope.data.MailingZip)) { $scope.errMsgZip = true; validForm = false; } However, it allows 12345-4. Shouldn't this be invalid? the last part should be either 4 digits or 0. – TechTurtle Jun 27 '16 at 14:26
  • 7
    A little late to the party, and maybe not the prettiest bell at the ball, but I've added additional optional spaces on either side of the hyphen - mostly for aesthetics. `/(^\d{5}(?:[\s]?[-\s][\s]?\d{4})?$)/` – Birrel Jul 29 '16 at 12:33
  • 1
    `/^\d{5}((?:[-\s]\d{4})|(\d{4}))?$/` - for formats 12345-6789, 123456789, 12345 – degr Jun 01 '17 at 11:22
  • A better way to allow for spaces around the hyphen is to just use: `[-\s]+` inside the (?...) block. Or if it would be an option to have no separator between the digits, then you could use `[-\s]*` I also like to match the first two digits separately to identify the state, so I expand out the first digits: `/^(\d\d)(\d\d\d)(?:[-\s]*\d{4})?$/`. – Damian Green Jul 29 '18 at 22:49
  • This regex `^\d{5}(?:[-\s]\d{4})?$` in the answer doesn't consider 57401-57402. I don't know if anyone verified that. – CodeForGood Dec 09 '21 at 14:25
7

For the listed three conditions only, these expressions might work also:

^\d{5}[-\s]?(?:\d{4})?$
^\[0-9]{5}[-\s]?(?:[0-9]{4})?$
^\[0-9]{5}[-\s]?(?:\d{4})?$
^\d{5}[-\s]?(?:[0-9]{4})?$

Please see this demo for additional explanation.

If we would have had unexpected additional spaces in between 5 and 4 digits or a continuous 9 digits zip code, such as:

123451234
12345 1234
12345  1234

this expression for instance would be a secondary option with less constraints:

^\d{5}([-]|\s*)?(\d{4})?$

Please see this demo for additional explanation.

RegEx Circuit

jex.im visualizes regular expressions:

enter image description here

Test

const regex = /^\d{5}[-\s]?(?:\d{4})?$/gm;
const str = `12345
12345-6789
12345 1234
123451234
12345 1234
12345  1234
1234512341
123451`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}
Emma
  • 27,428
  • 11
  • 44
  • 69
1

I know this may be obvious for most people who use RegEx frequently, but in case any readers are new to RegEx, I thought I should point out an observation I made that was helpful for one of my projects.

In a previous answer from @kennytm:

^\d{5}(?:[-\s]\d{4})?$

…? = The pattern before it is optional (for condition 1)

If you want to allow both standard 5 digit and +4 zip codes, this is a great example.

To match only zip codes in the US 'Zip + 4' format as I needed to do (conditions 2 and 3 only), simply remove the last ? so it will always match the last 5 character group.

A useful tool I recommend for tinkering with RegEx is linked below:

https://regexr.com/

I use this tool frequently when I find RegEx that does something similar to what I need, but could be tailored a bit better. It also has a nifty RegEx reference menu and informative interface that keeps you aware of how your changes impact the matches for the sample text you entered.

If I got anything wrong or missed an important piece of information, please correct me.

ZF007
  • 3,708
  • 8
  • 29
  • 48