2

I need to format belgian phone numbers. Depending on the city, the local prefix is either 1 or 2 characters long, and I can't figure how to write a single RegEx to match them all...

Here's what I've got so far, it works, but it takes 2 steps :

2 character prefix :

/(0{0,3}32)(93|92|89|87|86|85|84|83|82|81|80|71|69|67|65|64|63|62|61|60|59|58|57|56|55|54|53|52|51|50|28|26|25|22|19|16|15|14|13|12|11|10)([0-9]{2})([0-9]{2})([0-9]{2})/

1 character prefix :

/(0{0,3}32)(9|8|7|6|5|4|3|2)([0-9]{3})([0-9]{2})([0-9]{2})/

And the pattern :

"+$1 $2 $3 $4 $5"

Any idea how I can combine the two RegEx as well as using the same pattern for .replace() ?

2 Answers 2

2

How about a custom object that encapsulates checking and formatting?

function BelgianPhoneNumber(inputStr) {
    var re = /0{0,3}32(?:(9[23]|8[0-79|7[1]|6[0-579]|5[0-9]|2[2568]|1[0-69])([0-9]{2})|([2-9])([0-9]{3}))([0-9]{2})([0-9]{2})/,
        match, area, grp1, grp2, grp3;

    if (match = re.exec(inputStr)) {
        if (match[1]) {
            area = match[1];
            grp1 = match[2];
        } else {
            area = match[3];
            grp1 = match[4];
        }
        grp3 = match[5];
        grp4 = match[6];
    } else {
        area = grp1 = grp2 = grp3 = "";
        // possibly throw error
    }

    this.toString = function () {
        if (match) {
            return ["+32", area, grp1, grp2, grp3].join(" ");
        } else {
            return "invalid phone number: " + inputStr;
        }
    }
}

Usage

var p = new BelgianPhoneNumber("003233437667");
console.log("Phone: " + p);  // -> Phone: +32 3 343 76 67

var p = new BelgianPhoneNumber("003287565656")
console.log("Phone: " + p);  // -> Phone: +32 87 56 56 56

I have no idea whether the two numbering schemas can overlap, though, yielding false positives when matching.

However, when in doubt the regex favors 2-digit area codes over 1-digit ones. If you want it the other way around, change the order of the "choice..." group.

An argument for a custom object is that you could easily add methods like .getAreaCode() or one that maps area codes to city names. And you would still be able to use it directly in a string, thanks to the overridden .toString() method.

The combined regex breaks down as

0{0,3}32               # constant prefix, therefore no group
(?:                    # choice: either...
  (9[23]|8[0-79|7[1]|6[0-579]|5[0-9]|2[2568]|1[0-69])   # 2-digit area code
  ([0-9]{2})                                            # first group (2 digits)
  |                                                     # or...
  ([2-9])                                               # 1-digit area code
  ([0-9]{3})                                            # first group (3 digits)
)                      # end choice
([0-9]{2})             # second group (2 digits)
([0-9]{2})             # third group (2 digits)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks that helped me through understanding the regex posted earlier!
1

Your first regexp can be reduced to:

(0{0,3}32)(9[23]|8[0-79]|71|6[0-79]|5[0-9]|2[2568]|1[0-69])([0-9]{2})([0-9]{2})([0-9]{2})

Your second one can be also reduced to:

(0{0,3}32)([2-9])([0-9]{3})([0-9]{2})([0-9]{2})

This is one of the possible solutions to combine those two regexps:

(0{0,3}32)(?:(9[23]|8[0-79]|71|6[0-79]|5[0-9]|2[2568]|1[0-69])([0-9]{2})|([2-9])([0-9]{3}))([0-9]{2})([0-9]{2})

Every group you need is still accessible. The indexes of the groups changed though. To retrieve the format you provided in your question, replace the matching strings by:

+$1 $2$4 $3$5 $6 $7

Demo

8 Comments

Why not just make the unneccessary groups as non-capturing? That will not change the matching string.
@RohitJain If I well understood the inputs/outputs, every group is used. What unneccessary groups are you talking about?
I mean the outer groups you created to combine those regexes. Like this: - /(0{0,3}32)(?:(?:(9[23]|8[0-79]|71|6[0-579]|5[0-9]|2[25-68]|1[0-69])([0-9]{2}))|(?:([2-9])([0-9]{3})))([0-9]{2})([0-9]{2})/
And now captured groups are same. But it really won't matter much. It still does the job. +1. And yes - [2-3] is same as [23].
still can be non capturing: (?:)
|

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.