PO Box Regular Expression Validation
Here's my code, but I can't ever trigger the alert.
$(document).ready( function (){
$("[id*='txtAddress1S']").blur(function() {
var pattern = new RegExp('\b[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]\b');
if ($("[id开发者_如何学编程*='txtAddress1S']").val().match(pattern)) {
alert('We are unable to ship to a Post Office Box.\nPlease provide a different shipping address.');
}
});
});
I tried several PO Box RegExp patterns found on the internet including the ones posted on Stack Overflow, none of them passed our test requirements. Hence, I posted our RegExp below and our test sets:
var poBox = /^ *((#\d+)|((box|bin)[-. \/\\]?\d+)|(.*p[ \.]? ?(o|0)[-. \/\\]? *-?((box|bin)|b|(#|n|num|number)?\d+))|(p(ost|ostal)? *(o(ff(ice)?)?)? *((box|bin)|b)? *(#|n|num|number)*\d+)|(p *-?\/?(o)? *-?box)|post office box|((box|bin)|b) *(#|n|num|number)? *\d+|(#|n|num|number) *\d+)/i;
var matches = [ //"box" can be substituted for "bin"
"#123",
"Box 123",
"Box-122",
"Box122",
"HC73 P.O. Box 217",
"P O Box125",
"P. O. Box",
"P.O 123",
"P.O. Box 123",
"P.O. Box",
"P.O.B 123",
"P.O.B. 123",
"P.O.B.",
"P0 Box",
"PO 123",
"PO Box N",
"PO Box",
"PO-Box",
"POB 123",
"POB",
"POBOX123",
"Po Box",
"Post 123",
"Post Box 123",
"Post Office Box 123",
"Post Office Box",
"box #123",
"box 122",
"box 123",
"number 123",
"p box",
"p-o box",
"p-o-box",
"p.o box",
"p.o. box",
"p.o.-box",
"p.o.b. #123",
"p.o.b.",
"p/o box",
"po #123",
"po box 123",
"po box",
"po num123",
"po-box",
"pobox",
"pobox123",
"post office box",
"Post Box #123"
];
var nonMatches = [
"The Postal Road",
"Box Hill",
"123 Some Street",
"Controller's Office",
"pollo St.",
"123 box canyon rd",
"777 Post Oak Blvd",
"PSC 477 Box 396",
"RR 1 Box 1020"
];
In javascript, you have to escape your slashes:
var pattern = new RegExp('\\b[P|p]*(OST|ost)*\\.*\\s*[O|o|0]*(ffice|FFICE)*\\.*\\s*[B|b][O|o|0][X|x]\\b');
Also, you could reduce your pattern a bit by using case-insensitive matching:
var pattern = new RegExp('\\b[p]*(ost)*\\.*\\s*[o|0]*(ffice)*\\.*\\s*b[o|0]x\\b', 'i');
Note: Your regex also matches on addresses such as:
- 123 Poor Box Road
- 123 Harpo Box Street
I would suggest also checking for a number in the string. Perhaps this pattern from a previous answer would be of some help:
var pattern = new RegExp('[PO.]*\\s?B(ox)?.*\\d+', 'i');
(it won't match on "Post Office" spelled out, or the numeric replacements.. but it's a start.)
With Javascript its easier to use a regex literal like so:
var pattern = /\b(?:p\.?\s*o\.?|post\s+office)\s+box\b/i;
(No backslashes required!)
This is what i have used accounting for spaces and case insensitive:
http://regexr.com/3cc2q
var pattern = /\bP(ost|ostal)?([ \.]*(O|0)(ffice)?)?([ \.]*Box)\b/i;
- fail - po box
- fail - p.o. box
- fail - po bo
- fail - post office box
- fail - P.O. Box
- fail - PO. Box
- fail - PO Box
- fail - POBox
- fail - P O Box
- fail - P.O Box
- fail - PO
- fail - Postal Box
- fail - Post Office Box
- pass - poop box
- pass - pony box
We ran into false positive PO Boxes after using @Dathan's answer in production for a few months. This simplified version ensures the pattern is followed by a number so won't match things like "Expo Blvd". It also allows things like "#123" and "B1" commonly found in address2
fields for apartment/unit/suite numbers. You can play around with it and add your own test cases here: https://regex101.com/r/7ZUQFl/2
const re = /^\s*(.*((p|post)[-.\s]*(o|off|office)[-.\s]*(b|box|bin)[-.\s]*)|.*((p|post)[-.\s]*(o|off|office)[-.\s]*)|.*((p|post)[-.\s]*(b|box|bin)[-.\s]*)|(box|bin)[-.\s]*)(#|n|num|number)?\s*\d+/i;
const matches = [
"post office box 1",
"post office b 1",
"post off box 1",
"post off b 1",
"post o box 1",
"post o b 1",
"p office box 1",
"p office b 1",
"p off box 1",
"p off b 1",
"p o box 1",
"p-o-b-1",
"p.o.b.1",
"POB1",
"pob #1",
"pob num1",
"pob number1",
"foo pob1",
"box #1",
"po 1",
"pb 1"
];
const nonMatches = [
"Expo Blvd",
"Rural Route Box 1",
"Army Post 1",
"B1",
"#1",
"N1",
"Number 1",
"Num 1"
];
I found a pattern that works for most realistic post office addresses. Also had to fall to this after getting false positive with @jonathan-marzullo's answer for Rural Route Post 1
which is not a postal address.
My pattern is
pattern = P([.]?(O|0)[.]?|ost|ostal).((O|0)ffice.)?Box{1}\b/i
Matches for the following cases:
PO Box
P.O. Box
PO. Box
po box
P.o box
po box
p.o. box
post office box
P.O. Box
PO. Box
PO Box
Postal Box
Post Office Box
P.O Box
post office box 1
postal office box 1
postal box 1
Doesn't match the following cases:
post office b 1
post off box 1
post off b 1
post o box 1
post o b 1
p office box 1
p office b 1
p off box 1
p off b 1
p o box 1
p-o-b-1
p.o.b.1
POB
pob #1
pob num1
pob number1
foo pob1
box #1
po 1
pb 1
Expo Blvd
Rural Route Box 1
Army Post 1
postal office 1
poop box
pony box
POBox
P O Box
PO
po bo
Pobox
Post
This regex works for me in all the scenarios. The main difference between
^([ A-Za-z0-9_:/#,]*)((((((P(ost(al)?)?)|(Mail(ing)?)))([ \\./#-]*)((((O|0)(ffice)?)|(B(ox|in)?))))|(B(ox|in)?))([ \\./#-]*))(B(ox|in)?)?(([ \\./#-]*)((n(um(ber)?)?)|no)?)([ \\.:/#-]*)([0-9]+)([ A-Za-z0-9_:/#,]*)$
This regular expression matches the following set of address patterns.
I also added ([ A-Za-z0-9_:/#,]*) pattern in the beginning as well as at the end to support the presence of the patterns in between any other address string. Such as 123 Main St, P.O.Box 458.
The construct is defined as follows: (((Postal|Mailing){SEP}(Office|(Box|Bin)))|(Box|Bin)){SEP}(Box|Bin)?{SEP}(number|no){SEP}([0-9]+)
It addresses the concerns mentioned above by anson, drudge, rocky, jatto abdul
This is validated using Java 8+
Pattern pattern = Pattern.compile(REG_EX, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE );
boolean result = pattern.matcher(sequence).matches();
Passed
- P.O. Box: true
- p.O. Box: true
- p.o. Box: true
- PO Box: true
- Post Office Box: true
- Post Box: true
- po box: true
- post b: true
- po b: true
- Post: true
- Postal Office: true
- Post Office Box: true
- Postal Office Box: true
- Mailing Office Box: true
- Mail box: true
- Box 123: true
- Box-122: true
- Box122: true
- HC73 P.O. Box 217: true
- P O Box125: true
- P. O. Box: true
- P.O 123: true
- P.O. Box 123: true
- P.O. Box: true
- P.O.B 123: true
- P.O.B. 123: true
- P.O.B.: true
- P0 Box: true
- PO 123: true
- PO Box: true
- PO-Box: true
- POB 123: true
- POB: true
- POBOX123: true
- Po Box: true
- Post 123: true
- Post Box 123: true
- Post Office Box 123: true
- Post Office Box: true
- box #123: true
- box 122: true
- box 123: true
- P box: true
- P-o box: true
- P-o-box: true
- P.o box: true
- P.o. box: true
- P.o.-box: true
- P.o.b. #123: true
- P.o.b.: true
- P/o box: true
- Po #123: true
- Po box 123: true
- Po box: true
- Po num123: true
- Po-box: true
- Pobox: true
- Pobox123: true
- Post office box: true
- Post Box #123: true
Failed
- PO Box N: false
- number 123: false
- #123: false ( mentioned by Cole W. I removed it based on the similar logic mentioned by Tony Smith )
- 123 Main St: false
- 123 Poor Box St: false
- 123 Poor Box Road: false
- 123 Bin St: false
- 123 Harpo Box Street: false
- 123 Poblano Lane: false
- The Postal Road: false
- Box Hill: false
- 123 Some Street: false
- Controller's Office: false
- pollo St.: false
- 123 box canyon rd: false
- 777 Post Oak Blvd: false
This one is working pretty well for us. (php preg_match)
$pattern = '!p(ost)?\.?\s*o(ffice)?\.?(box|\s|$)!i';
Its worked for me,
var poRegex = /\bP(ost|ostal)?([ \.]*O(ffice)?)?([ \.]*Box)?\b/i;
Here's one that matches 'POB', 'PO Box'and 'Post Office Box'. Pattern:
\\b[PO.|Post\\sOffice]*\\s?B(ox)?.*\\d+\\b
.
It's a modification of @drudge
's solution.
The regex provided above is accepting PO box which is correct. Modified Regex not to accept is:
var pattern = /^ *(?!(#\d+)|((box|bin)[-. \/\\]?\d+)|(.*p[ \.]? ?(o|0)[-. \/\\]? *-?((box|bin)|b|(#|num)?\d+))|(p(ost)? *(o(ff(ice)?)?)? *((box|bin)|b)? *\d+)|(p *-?\/?(o)? *-?box)|post office box|((box|bin)|b) *(number|num|#)? *\d+|(num|number|#)|(?![a-zA-Z0-9\x20'#,]) *\d+)/i;
JavaScript:
^\b[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]\b
You just need to start the regex with ^
, like: ^\b[P|p]......
Here is my version(in Java):
- It should have a number after PO BOX
- A valid PO BOX can be part of a longer address like "My address details PO BOX 123" is a valid PO BIN address.
- It can use BIN instead of BOX
import java.util.Random;
import java.util.regex.Pattern;
public class Demo {
public static final Pattern POST_OFFICE_BOX_PATTERN = Pattern.compile("([\\w\\s*\\W]*(P(OST)?.?\\s*((O(FF(ICE)?)?)?.?\\s+B(IN|OX))+))\\s*\\d+[\\w\\s*\\W]*");
public static void main(String[] args) {
testInvalidAddresses();
testValidAddresses();
}
public static void testValidAddresses() {
String[] matches = new String[]{"HC73 P.O. Box 217",
"P O Box125",
"P.O. Box 123",
"PO Box " + Math.abs(new Random().nextInt()),
"PO Bin " + Math.abs(new Random().nextInt()),
"Post Office Box 123",
"Post Office Bin 123",
"Post Off. Box 123",
"Post Box 123",
"po bin 123"};
for (String address : matches) {
boolean isPoBox = isValidPostOfficeBox(address.toUpperCase());
if (!isPoBox) {
throw new IllegalArgumentException(address);
}
}
}
public static void testInvalidAddresses() {
var noMatches = new String[]{"#123",
"Box 123",
"Box-122",
"Box122",
"P. O. Box",
"P.O. Box",
"P.O.B 123",
"P.O.B. 123",
"P.O.B.",
"P0 Box",
"PO 123",
"PO Box",
"PO-Box",
"POB 123",
"POB",
"POBOX123",
"Po Box",
"Post 123",
"Post Office Box",
"box #123",
"box 122",
"box 123",
"p box",
"p-o box",
"p-o-box",
"p.o box",
"p.o. box",
"p.o.-box",
"p.o.b. #123",
"p.o.b.",
"p/o box",
"po #123",
"po bin",
"po box",
"po num123",
"po-box",
"pobox",
"pobox123",
"post office box",
"The Postal Road",
"Box Hill",
"123 Some Street",
"Controller's Office",
"pollo St.",
"123 box canyon rd",
"777 Post Oak Blvd",
"PSC 477 Box 396",
"RR 1 Box 1020",
"PzBzzzzzzzzz",
"PzzBzzzzzzzzz",
"PzzzBzzzzzzzzz",
"PzzzzBzzzzzzzzz",
"zzzPzBzzzzzzzzz",
"zzzPzzBzzzzzzzzz",
"zzzPzzzBzzzzzzzzz",
"zzzPzzzzBzzzzzzzzz",
"P.O 123",
"Washington Post 42",
"PO binary 123",
"p b",
"p b",
"Piebert",
"Pebble",
"pb"};
for (String address : noMatches) {
boolean isPoBox = isValidPostOfficeBox(address);
if (isPoBox) {
throw new IllegalArgumentException(address);
}
}
}
public static boolean isValidPostOfficeBox(String value) {
if (value != null) {
return POST_OFFICE_BOX_PATTERN.matcher(value.toUpperCase()).matches();
}
return false;
}
}
If you stripped out all the dots "." and spaces then converted it lower case you would only need to check if the string starts with pob
or postofficebox
,
(credit BarCotter)
I used following JavaScript regex for my project requirements.
/((((p[\s\.]?)\s?[o\s][\.]?)\s?)|(post\s?office\s?)|(postal\s?)|(post\s?))((box|bin|b\.?)?\s?((num|number|no|#)\.?)?\s?\d+)/igm.test(v);
Following are not allowed.
po 123
pob 555
p.o.b. 555
po box 555
pobox 555
p.o. box 663
P.O. Box #123
P.O. Box 3456
PO Box 1234
PO Box Num 1234
P O Box 4321
Post Office Box 9999
postal box 123
postal box #123
postal b 123
postal bin #45
postal bin 35
postal bin number 678
postal bin no 980
down street PO box 123
po bin 123
po bin #45
po number 45
p.o.#54
p.o #54
P.o.B #45
POB 54
POB# 454
POb #65464
My apartment floor 23 po box 34
Down town, near supermarket postal box 45
bin postal 123
Following are allowed
95 CAPON ST NE, PALM BAY, FL, 32905
713 BIGGIN POND RD
123 Poor Box Road
123 Harpo Box Street
The Postal Road
#43 The postal Road
Box Hill
123 Some Street
Controller's Office
pollo St.
123 box canyon rd
777 Post Oak Blvd
PSC 477 Box 396
RR 1 Box 1020
demo village 123
House #4, near lampost
3rd lane Radio communication Pole
Second house from Polly store
4th house from postal office
Fox cinema post #123
精彩评论