1

Is there any way to do a Regex Replace conditionally? Here's an example.

Say you have a number that you know corresponds to a phone, with no formatting:

5553331234

Formatted, it would be

(555)333-1234

However, we don't have the number formatted and want to apply formatting. You can do an easy regex match and capture each of the 3 groups with something along the following:

(\d{3})(\d{3})(\d{4})

From there, you can do a simple regex replace

($2)$3-$4

However, what if you might have an extension? Maybe you have more than the 10 standard phone digits:

555333123456789

Where 56789 would be an extension. In that case, I could match it with

(\d{3})(\d{3})(\d{4})(\d*)

If I want to format it, but only include the X for extension if it exists, can I do that? For instance, I could make my replace format:

($2)$3-$4x$5

However, if I did that, the x would show up even when there is no extension. Is there a way purely using the regex to make that x show up conditionally? Essentially it would be "if $5" exists or "if $5.Length() > 0".

As a workaround, I could include a named group in that regex match where (\d*) above becomes

(?<Conditional>\d*)

In the code, I could then assert the length of the group named "Conditional". However, I'd like to have a purely regex solution that does not require anything custom like that.

2 Answers 2

2

Take a look at Substitutions in Regular Expressions - there's no replacement pattern that would allow you to write a conditional. Other libraries, like boost::regex do provide such facilities, but you don't get that in .NET.

What you do get though is the ability to use a callback to supply the replacement. Just use a lambda:

Regex.Replace(
    "555333123456789",
    @"(\d{3})(\d{3})(\d{4})(\d+)?",
    m => $"({m.Groups[1].Value}){m.Groups[2].Value}-{m.Groups[3].Value}{(m.Groups[4].Success ? $"x{m.Groups[4].Value}" : "")}"
)

Yes, I know that's not a pure regex solution, but it does its job. Remember that substitution is not really a regex operation, it's rather a post-matching step which does involve the result of a match but does not involve the regex engine itself.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use the overload of Regex.Replace that takes a MatchEvaluator which will allow you to do conditional logic based on the matched groups.

var phone = "5553331234";
Regex phoneRegex = new Regex(@"(\d{3})(\d{3})(\d{4})(\d*)");
var formatted = phoneRegex.Replace(
    phone, 
    m => string.Format(
        "({0}){1}-{2}{3}{4}", 
        m.Groups[1].Value, 
        m.Groups[2].Value, 
        m.Groups[3].Value, 
        m.Groups[4].Value.Length > 0 ? "x" : string.Empty, 
        m.Groups[4].Value));
Console.WriteLine(formatted);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.