How to make a regular expression for mobile phone?

How to create a regular expression to validate the phone field you accept 99-99999999 (DDD + 8 numbers) or 99-999999999 (DDD + 9 numbers). And that when typing it adds The Dash - automatically!

ValidationExpression="^[0-9]{2}-([0-9]{8}|[0-9]{9})"

How to proceed?

Author: Renan Gomes, 2015-01-13

5 answers

Nowadays all mobile phones in Brazil have nine digits and start with the digit 9 and all landline phones have 8 digits and never start with the digit 9. I personally would prefer to format the phone as (xx) xxxxx-xxxx. Therefore, the best regular expression for this would be this:

^\([1-9]{2}\) (?:[2-8]|9[1-9])[0-9]{3}\-[0-9]{4}$

The full explanation of it is:

  • ^ - start of string.
  • \( - One opens parentheses.
  • [1-9]{2} - two digits from 1 to 9. There are no codes of DDD with the digit 0.
  • \) - one closes parentheses.
  • - a blank.
  • (?:[2-8]|9[1-9]) - the beginning of the number. Represents a choice between a digit between 2 and 8 (the part of [2-8]) and a 9 followed by a digit from 1 to 9 (the part of 9[1-9]). The | separates the options to be chosen. (?: ... ) groups such choices. Landline phones start with digits from 2 to 8. Mobile phones start with 9 and have a second digit from 1 to 9. The first digit never it will be 0 or 1. Cell phones can't start with 90 because that's the prefix for calls to charge.
  • [0-9]{3} - the remaining three digits of the first half of the phone number, making a total of 4 or 5 digits in the first half.
  • \- - a hyphen.
  • [0-9]{4} - the second half of the phone number.
  • $ - end of string.

If you want to leave parentheses, whitespace and hyphen optional, then you can put a ? after each of these symbols, resulting in this regular expression:

^\(?[1-9]{2}\)? ?(?:[2-8]|9[1-9])[0-9]{3}\-?[0-9]{4}$

If you want, you can also filter the DDDs that exist. Here is an image that shows the currently existing area codes according to the Wikipedia :

Map of Brazil with divisions by DDD

Then looking at this map, the subexpression that would filter out valid DDDs would be as follows:

(?:[14689][1-9]|2[12478]|3[1234578]|5[1345]|7[134579])

As already explained, the (?: ... ) is for grouping. The options (separate by |) would be two-digit groups, which would be one of the following options: 2[12478] for Rio de Janeiro and Espírito Santo, 3[1234578] for Minas Gerais, 5[1345] for Rio Grande do Sul, 7[134579] for Bahia and Sergipe and [14689][1-9] for the rest of Brazil.

And the full regular expression would be as follows (with the required parentheses, spaces, and hyphens):

^\((?:[14689][1-9]|2[12478]|3[1234578]|5[1345]|7[134579])\) (?:[2-8]|9[1-9])[0-9]{3}\-[0-9]{4}$

And with them not mandatory:

^\(?(?:[14689][1-9]|2[12478]|3[1234578]|5[1345]|7[134579])\)? ?(?:[2-8]|9[1-9])[0-9]{3}\-?[0-9]{4}$

Note: This answer was originally written in 2015, when there were 8-or 9-digit cell phones, depending on the DDD. Since then, it has been updated to the newest format in force, which always have 9 digits. For more details on how this response was edited, check out the edit history.

 65
Author: Victor Stafusa, 2020-11-01 10:43:38

My solution may not be the most effective, but since I did not see many solutions commenting on some points I decided to write mine.

I created a regular expression that identifies whether a string is a phone, taking into account the following cases:

  • 0800 phones
  • carrier and service numbers such as 10315 and 190
  • phones represented with or without parentheses
  • accepts operator represented as 0xx11
  • phones with or without the [tabs .-]
  • ignores phones starting with 0 if it does not have DDD (ex: 0999-9999 is not accepted, but 0xx11 9123-1234 is)

Got a little big and hard to read humanly, but it caters to my projects:

/^1\d\d(\d\d)?$|^0800 ?\d{3} ?\d{4}$|^(\(0?([1-9a-zA-Z][0-9a-zA-Z])?[1-9]\d\) ?|0?([1-9a-zA-Z][0-9a-zA-Z])?[1-9]\d[ .-]?)?(9|9[ .-])?[2-9]\d{3}[ .-]?\d{4}$/gm

You can see the expression in use in this link .

After you validate if the expression is a phone, you can format it the way you see fit by manipulating the string.

Follows an example in Java (where PHONE_MATCH is the regular expression):

public String phone(String phoneString) throws IllegalArgumentException {
    if (!phoneString.matches(PHONE_MATCH)) {
        throw new IllegalArgumentException("Not a valid phone format");
    }

    String str = phoneString.replaceAll("[^\\d]", "");

    if (str.charAt(0) == '0') {
        if (str.charAt(1) == '0') {
            str = str.substring(2);
        } else {
            str = str.substring(1);
        }
    }

    switch (str.length()) {
        case 8:
            return applyMask(str, "AAAA-AAAA", 'A');
        case 9:
            return applyMask(str, "AAAAA-AAAA", 'A');
        case 10:
            return applyMask(str, "(AA) AAAA-AAAA", 'A');
        case 11:
            return applyMask(str, "(AA) AAAAA-AAAA", 'A');
        default:
            return str;
    }
}

ApplyMask Method:

public String applyMask(String str, String mask, char specialChar) {

    // Conta quantos caracteres especiais existem na máscara
    int maskChCount = mask.length() - mask.replaceAll("[^" + specialChar + "]", "").length();

    // Conta apenas os números
    int strChCount = str.length() - str.replaceAll("\\d", "").length();

    // Exceção caso a string nao tenha números suficientes para competar a máscara
    if (strChCount < maskChCount) {
        throw new IllegalArgumentException("The number of chars in the string should not be smaller than the " +
                "number of special chars in the mask");
    }

    char[] maskChars = mask.toCharArray();
    char[] strChars = str.toCharArray();

    // Itera por todos os elementos da máscara
    for (int i = 0, j = 0; i < maskChars.length && j < strChars.length; i++) {
        char ch = maskChars[i];
        char sh = strChars[j];

        if (ch == specialChar) {
            // Se achou o caractere especial, buscar o próximo elemento aceito da String e 
            // substituí-lo no local do caractere especial
            while (!Character.toString(sh).matches("\\d")) {
                j++;
                sh = strChars[j];
            }
            maskChars[i] = sh;
            j++;
        }
    }

    return new String(maskChars);
}

I believe you have several ways to optimize this code, any suggestion is welcome.

 10
Author: Felipe Andrade, 2016-09-01 18:00:22

I use this

@"^\(?\d{2}\)?[\s-]?[\s9]?\d{4}-?\d{4}$"

If you put 9 digits she thanks you that the first digit is 9.

I would take a little of each example to assemble the ideal.

 4
Author: Gabriel Santos Reis, 2015-08-26 20:36:23

Folks, with your help I created a string that I thought was right for me. Simple and straightforward. In WHMCS use to start and close /. I will not use the example to follow your example. Come on. The expression looks like this:

^\([1-9]{2}\) [9]{0,1}[6-9]{1}[0-9]{3}\-[0-9]{4}$

Explanation:

  • ^ = start of string.
  • \( = One opens parentheses.
  • [1-9]{2} = two digits from 1 to 9. There are no DDD codes with the digit 0.
  • \) = one closes parentheses.
  • = Um espaço em branco.
  • [9]{0,1} = O first digit is 9, plus it may or may not exist hence the " 0 " or "1" within the {0,1}.
  • [6-9]{1} = the second digit can be from 6 to 9.
  • [0-9]{3} = the other three digits are from 0 to 9
  • \- = a hyphen.
  • [0-9]{4} = the second half of the phone number.
  • $ = end of string.

Reminding friends that in WHMCS one should start and close with/. By the end of 2016 or more accurate on November 06, 2016 all of Brazil will have the 9 in start of mobile phones.

 2
Author: Fábio Seabra, 2016-04-12 17:26:35
^\([1-9]{2}\) 9[7-9]{1}[0-9]{3}\-[0-9]{4}$
  • [1-9]{2} = two digits from 1 to 9. There are no DDD with the digit 0.
  • 9 = all mobiles as of 2016 start with 9
  • [7-9]{1} = in the old numbering the phones started with 7, 8 or 9
  • [0-9]{3} = the other three digits can be from 0 to 9
  • [0-9]{4} = the four after the hyphen can be from 0 to 9
 1
Author: Eduardo de Souza, 2019-03-14 14:27:18