0

Currently, I am looping through phone numbers to find matches in a database. However, I need to remove dashes and any area codes so that the database search can exact. Currently, I am trying to use this regex on the phone numbers :

(?:\+\d{2}\s*(?:\(\d{2}\))|(?:\(\d{2}\)))?\s*(\d{4,5}\-?\d{4})

and I am trying to apply it as such

       if let longNumber = (contact.phoneNumbers.first?.value as? CNPhoneNumber)?.stringValue  {
                    let phoneNumber = longNumber.replacingOccurrences(of: "(?:\+\d{2}\s*(?:\(\d{2}\))|(?:\(\d{2}\)))?\s*(\d{4,5}\-?\d{4})", with: "$1", options: .regularExpression)

However, I receive the error Invalid escape sequence in literal and Missing argument for parameter 'for' in call

How can I properly get only the phone digits from the string? ie if it is +1 300-300-3000

I need it to return 3003003000.

Examples:

+1 390 - 456 - 8823 -> 3904568823

+92 084 765 4902 --> 0847654902

+922 (064) 864 0921 --> 0648640921

842.231.9072 --> 8422319072

+1 (972) - 864 - 0921 --> 9728640921

+92 33 - 783 - 9382 --> 337839282

7
  • You need to escape your backslashes, so the compiler doesn't interpret them as escape characters and instead passes them to the regex. Commented Oct 8, 2018 at 1:27
  • Maybe you know some characters needs to be escaped inside String literal, for example a string with one double-quite is represented like this: "\"". Backslash `\` is another character which needs to be escaped. But even if such escaping fixed, your pattern cannot match phone numbers with two hyphens or more. Commented Oct 8, 2018 at 1:28
  • Have you tried NSDataDetector? It’s a subclass of NSRegularExpressionbuilt to detect certain things like dates, events and phone numbers. Commented Oct 8, 2018 at 1:41
  • @OOPer do you know a better regex pattern I can use? Commented Oct 8, 2018 at 2:03
  • @CodeDifferent would NSDataDetector be able to remove all hyphens and area codes, too? Commented Oct 8, 2018 at 2:03

1 Answer 1

1

From the examples you have shown, I assume the following rules:

Phone numbers are formatted in 3 or 4 parts

Part1 (optional)

  • +
  • 1 to 3 digits
  • one or more whitespaces follow

Part2

  • May be enclosed in ( and )
  • 2 or 3 digits
  • a hyphen or a decimal point or a whitespace with extra whitespaces at both ends follows

Part3

  • 3 digits
  • a hyphen or a decimal point or a whitespace with extra whitespaces at both ends follows

Part4

  • 4 digits

(Please remember, this sort of phone number notation rule is local to a specific region. When you want to internationalize your app, you may need many more rules. The pattern you have now may be written for some other region.)

Partial pattern for each part would be something as follows:

let part1 = "(?:\\+\\d{1,3}\\s+)?"
let part2 = "(?:\\((\\d{2,3})\\)|(\\d{2,3}))\\s*[\\s\\.-]?\\s*"
let part3 = "(\\d{3})\\s*[\\s\\.-]?\\s*"
let part4 = "(\\d{4})"

(Please do not miss that all backslashes are escaped.)

Testing code:

import Foundation

let numbers: [(long: String, expected: String)] = [
    ("+1 300-300-3000",       "3003003000"),
    ("+1 390 - 456 - 8823",   "3904568823"),
    ("+92 084 765 4902",      "0847654902"),
    ("+922 (064) 864 0921",   "0648640921"),
    ("842.231.9072",          "8422319072"),
    ("+1 (972) - 864 - 0921", "9728640921"),
    ("+92 33 - 783 - 9382",   "337839382"),   //I assume your example is wrong here
]
for number in numbers {
    let longNumber = number.long
    let part1 = "(?:\\+\\d{1,3}\\s+)?"
    let part2 = "(?:\\((\\d{2,3})\\)|(\\d{2,3}))\\s*[\\s\\.-]?\\s*"
    let part3 = "(\\d{3})\\s*[\\s\\.-]?\\s*"
    let part4 = "(\\d{4})"
    let pattern = "^\(part1)\(part2)\(part3)\(part4)$"
    let phoneNumber = longNumber.replacingOccurrences(of: pattern, with: "$1$2$3$4", options: .regularExpression)
    print("\(longNumber) --> \(phoneNumber)", phoneNumber == number.expected ? "Success" : "Fail (expected \(number.expected))")
}

Output:

+1 300-300-3000 --> 3003003000 Success
+1 390 - 456 - 8823 --> 3904568823 Success
+92 084 765 4902 --> 0847654902 Success
+922 (064) 864 0921 --> 0648640921 Success
842.231.9072 --> 8422319072 Success
+1 (972) - 864 - 0921 --> 9728640921 Success
+92 33 - 783 - 9382 --> 337839382 Success

The code above may not work as expected for possible other inputs, please try to fix it to fit for such inputs by yourself.

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

3 Comments

to be honest, I am not really sure about regex that much and its syntax - I am still learning. However, I was considering that there would be a way to make the regex more applicable to all inputs, something along the lines that simply removed everything that wasn't a number and then remove the numbers immediately following a plus sign but before a space. Would something like this be possible? Appreciate your time.
@RaimKhalil, that seems to be a better option when you need to work with many possible variation of phone number formats. But, in my opinion, it's a little bit too far from your original question. You should better start a new thread with your requirement clarified as in your comment.
will do, and Ill mark your answer as correct as it does properly answer the question I asked.

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.