tags:

views:

337

answers:

4

I need regular expression that matches a pattern or is empty.

Right now I have an expression...

"\(?\d{3}\)?[-\s.]?\d{3}[-\s.]\d{4}/x"

... which matches US phone numbers. However, it is valid for the string I'm testing to be empty. If the string has any value in it at all, it must match the expression.

I have other patterns which match US postal codes, etc that need the same conditional.

What is the best way to achieve this in the same expression?

Clarification: I am using the RegexValidator in the Validation Application Block from Microsoft. An example of using this is as follows:

    [StringLengthValidator(0, 100, MessageTemplate = "Email must be between {3} and {5}")]
    [RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", MessageTemplate = "Valid Email Required.")]
    public string EmailAddress
    {
        get { return _EmailAddress; } 
        set { SetValue<string>(ref _EmailAddress, value); }
    }

This is why I need the solution to be in one expression.

+3  A: 

Wrap the entire regex in parens and place a ? at the end:

(\(?\d{3}\)?[-\s.]?\d{3}[-\s.]\d{4}/x)?
Kevin Crowell
worked like a charm. i knew it would be something simple like this. :)
Sailing Judo
actually... this doesn't work right. the trailing question mark appears to make the regex too forgiving. For example, 555-1234 will now match but it shouldn't.
Sailing Judo
Assuming your original regex works, you can try: \B|\(?\d{3}\)?[-\s.]?\d{3}[-\s.]\d{4}/xWhich should be "empty string" OR your regex
Kevin Crowell
Same issue. My original regex (without the /x) works on this test site (http://www.nvcc.edu/home/drodgers/ceu/resources/test_regexp.asp). If I add the options you suggest then I can type anything in the test and it passes.
Sailing Judo
\B means "not a word boundary". It will match an empty string, but it doesn't communicate your intention very well. Your original suggestion is much better, and should have worked.
Alan Moore
Found the issue... yours works fine if I add the ^ at the front and a $ at the end.
Sailing Judo
Thanks for the clarification Alan. I never actually use \B
Kevin Crowell
A: 

Try wrapping your regex with (?:<your_regex>)?.

Andrew Hare
+1  A: 

Try this:

@"^(?:(\()?\d{3}(?(1)\)|[-\s.])\d{3}[-\s.]\d{4})?$"

The (?(1)\)|[-\s.]) part is a conditional construct. It says "If there was a '(' at the beginning (which we know because group #1 matched something), match a ')' here; otherwise match a hyphen, whitespace or dot." And wrapping the whole thing in (?:...)? allows it to match an empty string, just as Kevin said; if that didn't work for you, you must have misplaced one of the parens (or maybe one of the backslashes).

I added the ^ and $ anchors for testing purposes; in a validator control they shouldn't be needed.

Alan Moore
Curiously, your regex completely crashes the expressing checking site I've been using (http://www.nvcc.edu/home/drodgers/ceu/resources/test_regexp.asp). However, +1 because the general idea works.
Sailing Judo
Do you know if that site uses the .NET regex engine? It works fine here: http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx
Alan Moore
A: 

Also needed to match a pattern or an empty string, worked great, thanks allot! ;)

Fico