4

I've tried a few things, haven't been able to get it to work. I need to exclude PO Boxes. I thought I just had to wrap it with ?!..but it is not working. Any thoughts?

^((?i)[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]\s*(\d.))*$

EDIT: Sorry, this is what I am looking for.

Example: when input is "P.O. BOX" or "Post Office" I need regex to be false. When input is 7821 Test street, I need regex to be true.

I am attempting to use it in an ASP.net MVC project

/// <summary>
/// Regex for street fields
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple =     false)]
public class StreetAddressAttribute : RegularExpressionAttribute, IClientValidatable
{
/// <summary>
/// Regular expression validation for street field
/// </summary>
public StreetAddressAttribute()
  : base(@"^(?!(?i)[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]\s*(\d.)*)$")
{
}

 /// <summary>
 /// Client side validation
 /// </summary>
 /// <param name="metadata">Modelmetadata</param>
 /// <param name="context">ControllerContext</param>
 /// <returns>Client-side validation rules</returns>
 public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata    metadata, ControllerContext context)
 {
   yield return new ModelClientValidationRule { ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), ValidationType = "streetaddress" };
 }
}

Thanks for your help

Matt
  • 22,721
  • 17
  • 71
  • 112
Ricka
  • 247
  • 3
  • 11
  • 2
    Can you explain in real-world terms what possible values you are looking to match? – Mike Brant May 23 '13 at 19:58
  • Do you want to exclude all PO boxes or even APO boxes (overseas US military)? – jle May 23 '13 at 20:05
  • 2
    I wouldn't use a regex (because that's just adding a new problem). I think a simpler "string contains any of 'po box', 'p.o. box', 'post office box', etc" works better. – Dai May 23 '13 at 20:12
  • Why not match a PO box then negate that return value? – Matt May 23 '13 at 20:12
  • I could try and rethink the whole thing. However, I can't negate a return value currently as the regex is just sent to the browswer as an attribute: data-val-regex-pattern="^(?!(?i)[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]\s*(\d.)*)$" – Ricka May 23 '13 at 20:25
  • What about malformed addresses like 128 PO Box? @MikeBrant is right. It would be very helpful to know what you are using this for. Perhaps there is a better solution if you can provide more info for us. – Jeffrey May 23 '13 at 20:40

1 Answers1

7

Your regex has so many issues, I try to address one after the other

  1. In a Character class you don't need a | as an OR. Every character inside is added to the allowed characters list. So doing a [P|p] allows the three characters "P", "p" and "|".

    The correct class would be [Pp]

  2. You use the inline modifier (?i). This makes the following letters all matched case independent. So [Pp] is unnecessary, just p is enough to match the letters "P" and "p".

    Including this first two issues we can change your expression to

     ^(?!(?i)p*(ost)*\.*\s*[Oo0]*(ffice)*\.*\s*b[o0]x\s*(\d.)*)$
    
  3. You made everything except b[o0]x repeatable 0 or more times by the * quantifier. I am quite sure this is not what you want, or do you want to find things like "pppppppostostb0x"?

The regex that is false, when the input is "P.O. BOX" or "Post Office" is more like this:

^(?i)(?!p\.?o\.?\sbox|post\soffice).*$

This regex would match every string (because of the .* at the end), except strings that start like this like this:

  • po box
  • p.o box
  • p.o. box
  • Post Office
  • POST oFfIcE
Community
  • 1
  • 1
stema
  • 90,351
  • 20
  • 107
  • 135