0

This is not a duplicate, the linked thread does not explain how to achieve this.

I'm looking to get a phone number in a specific format.

+xx (x) xxx xxx xxxx

  • Country code.
  • Space.
  • Zero in brackets.
  • Space.
  • 3 digits.
  • Space.
  • 3 digits.
  • Space.
  • 4 digits.

The user could type anything in (but should always be a +61 number). So far I have tried the below.

  • Removing spaces and non numeric characters.
  • If starting with a zero, remove.
  • If starting with 610, remove.
  • If starting with 61, remove.
  • Re add country code in specific format and format rest of phone number is a 3,3,4 format.

My question, is - is there a way to simply the below to perhaps one expression?

    value = value.replace(/\D/g,'');
    value = value.startsWith(0) ? value.substring(1) : value;
    value = value.startsWith('610') ? value.substring(3) : value;
    value = value.startsWith('61') ? value.substring(2) : value;
    value = '+61 (0) ' + value.replace(/\d{3,4}?(?=...)/g, '$& ');
panthro
  • 22,779
  • 66
  • 183
  • 324

2 Answers2

1

To expand and explain on @splash58's comment they propose using two regular expressions to do the full replacement you desire. The first(/\D|(0+|610|61)/gi) will remove all unwanted characters within the string. The second (/(\d{3})(\d{3})(\d{4})/gi) will take the remaining digits and capture the desired groupings so you can format them as desired. I highly suggest looking at the regex101 links they provided as that site will fully explain how and why a given expressions matches what it does on the right.

Short version:

/\D|(0+|610|61)/gi will match any NON-digit character OR a string of 0s, "610" or "61". Replace this with nothing to remove

/(\d{3})(\d{3})(\d{4})/gi will match a string of 10 digits and capture groups, that's what the parentheses are, of 3 digits, 3 digits and 4 digits. These can be referenced in the replacement as identifiers $1, $2 and $3 according to their position.

Putting it all together:

// look in a string and return formatted phone number only
function phone(str) {
    str = str.replace(/\D|(0+|610|61)/gi, '');
    str = str.replace(/(\d{3})(\d{3})(\d{4})/gi, '+61 (0) $1 $2 $3');
    return str;
}
console.log(phone('xgsh6101231231234vvajx'));
console.log(phone('+6101231231234'));

I would also recommend first doing a search on the entire input string for a series of numbers or whitespace so that you end up with less false positives. This can be done with a regular expression like /[\d\s]+/

jjspace
  • 178
  • 2
  • 11
  • Thanks but the above does not work if the user types in +6101231231234 It adds another 61 in the phone number after +61 (0) 61.... – panthro Oct 23 '18 at 16:35
  • Only add `\+?` to regex – splash58 Oct 23 '18 at 17:03
  • 1
    @panthro And it will be better to show examples of input you expect – splash58 Oct 23 '18 at 17:04
  • @panthro are you sure you implemented it as shown? the input you just provided works fine for me. I've added on to the example and if you hit run now you will see that it works here. – jjspace Oct 23 '18 at 17:08
0

You might match the number using:

^.*?\+?0*610?(\d{3})(\d{3})(\d{4})(?!\d).*$

Regex demo

And replace with:

+61 (0) $1 $2 $3

Explanation

  • ^ Assert the start of the string
  • .*? Match 0+ characters non greedy
  • \+? Match an optional plus sign
  • 0*610? Match 0+ times a zero, 61 with optional zero
  • (\d{3})(\d{3})(\d{4}) match 3 groups with 3, 3, and 4 digits
  • (?!\d) Negative lookahead to assert what follows is not a digit
  • .* Match 0+ characters
  • $ Assert the end of the string

const strings = [
  "xgsh6101231231234vvajx",
  "xgsh06101231231234vvajx",
  "xgsh000006101231231234vvajx",
  "+6101231231234",
  "xgsh61012312312345vvajx",
  "xgsh5101231231234vvajx",
  "xgsh00000101231231234vvajx",
  "xgsh6143545626455345601231231234vvajx"
];
let pattern = /^.*?\+?0*610?(\d{3})(\d{3})(\d{4})(?!\d).*$/;

strings.forEach((s) => {
  console.log(s.replace(pattern, "+61 (0) $1 $2 $3"));
});
The fourth bird
  • 154,723
  • 16
  • 55
  • 70