«1. Обзор

Иногда нам нужно проверить текст, чтобы убедиться, что его содержимое соответствует какому-либо формату. В этом кратком руководстве мы увидим, как проверять различные форматы телефонных номеров с помощью регулярных выражений.

2. Регулярные выражения для проверки телефонных номеров

2.1. Десятизначное число

Начнем с простого выражения, которое проверяет, состоит ли число из десяти цифр и ничего больше:

@Test
public void whenMatchesTenDigitsNumber_thenCorrect() {
    Pattern pattern = Pattern.compile("^\\d{10}$");
    Matcher matcher = pattern.matcher("2055550125");
    assertTrue(matcher.matches());
}

Это выражение позволяет использовать числа вроде 2055550125.

2.2. Число с пробелами, точками или дефисами

Во втором примере давайте посмотрим, как мы можем разрешить необязательные пробелы, точки или дефисы (-) между числами:

@Test
public void whenMatchesTenDigitsNumberWhitespacesDotHyphen_thenCorrect() {
    Pattern pattern = Pattern.compile("^(\\d{3}[- .]?){2}\\d{4}$");
    Matcher matcher = pattern.matcher("202 555 0125");
    assertTrue(matcher.matches());
}

Для достижения этой дополнительной цели (необязательные пробелы или дефис), мы просто добавили символы:

    [- .]?

Этот шаблон позволяет использовать такие номера, как 2055550125, 202 555 0125, 202.555.0125 и 202-555-0125.

2.3. Число со скобками

Теперь давайте добавим возможность иметь первую часть нашего телефона в скобках:

@Test
public void whenMatchesTenDigitsNumberParenthesis_thenCorrect() {
    Pattern pattern = Pattern.compile"^((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
    Matcher matcher = pattern.matcher("(202) 555-0125");
    assertTrue(matcher.matches());
}

Чтобы разрешить необязательные скобки в числе, мы добавили следующие символы в наше регулярное выражение:

    (\\\\(\\\\d{3}\\\\))|\\\\d{3})

Это выражение позволяет использовать такие числа, как (202)5550125, (202) 555-0125 или (202)- 555-0125. Кроме того, это выражение также позволит использовать телефонные номера, описанные в предыдущем примере.

2.4. Номер с международным префиксом

Наконец, давайте посмотрим, как разрешить международный префикс в начале номера телефона:

@Test
public void whenMatchesTenDigitsNumberPrefix_thenCorrect() {
  Pattern pattern = Pattern.compile("^(\\+\\d{1,3}( )?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
  Matcher matcher = pattern.matcher("+111 (202) 555-0125");
  
  assertTrue(matcher.matches());
}

Чтобы разрешить префикс в нашем номере, мы добавили в начало шаблона символы :

    (\\\\+\\\\d{1,3}( )?)?

Это выражение позволит телефонным номерам включать международные префиксы, принимая во внимание, что международные префиксы обычно представляют собой номера, состоящие не более чем из трех цифр.

3. Применение нескольких регулярных выражений

Как мы видели, допустимый номер телефона может принимать несколько различных форматов. Поэтому мы можем захотеть проверить, соответствует ли наша строка любому из этих форматов.

В предыдущем разделе мы начали с простого выражения и усложнили его, чтобы достичь цели охвата более одного формата. Однако иногда невозможно использовать только одно выражение. В этом разделе мы увидим, как объединить несколько регулярных выражений в одно.

Если мы не можем создать общее регулярное выражение, которое может проверять все возможные случаи, которые мы хотим охватить, мы можем определить разные выражения для каждого из случаев, а затем использовать их все вместе, объединив их с помощью символа вертикальной черты ( |).

Давайте рассмотрим пример, в котором мы используем следующие выражения:

    Выражение, использованное в последнем разделе: ^(\\\\+\\\\d{1,3}( )?)?((\\\\(\\\\ d{3}\\\\))|\\\\d{3})[- .]?\\\\d{3}[- .]?\\\\d{4}$ Регулярное выражение, разрешающее такие числа, как +111 123 456 789 : ^(\\\\+\\\\d{1,3}( )?)?(\\\\d{3}[ ]?){2}\\\\d{3}$ Шаблон, позволяющий использовать такие числа, как +111 123 45 67 89: ^(\\\\+\\\\d{1,3}( )?)?(\\\\d{3}[ ]?)(\\\\d{2}[ ]?){2}\\\\d{2 }$
@Test
public void whenMatchesPhoneNumber_thenCorrect() {
    String patterns 
      = "^(\\+\\d{1,3}( )?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$" 
      + "|^(\\+\\d{1,3}( )?)?(\\d{3}[ ]?){2}\\d{3}$" 
      + "|^(\\+\\d{1,3}( )?)?(\\d{3}[ ]?)(\\d{2}[ ]?){2}\\d{2}$";

    String[] validPhoneNumbers 
      = {"2055550125","202 555 0125", "(202) 555-0125", "+111 (202) 555-0125", 
      "636 856 789", "+111 636 856 789", "636 85 67 89", "+111 636 85 67 89"};

    Pattern pattern = Pattern.compile(patterns);
    for(String phoneNumber : validPhoneNumbers) {
        Matcher matcher = pattern.matcher(phoneNumber);
        assertTrue(matcher.matches());
    }
}

Как видно из приведенного выше примера, с помощью символа вертикальной черты мы можем использовать три выражения за один раз, что позволяет охватить больше случаев, чем с помощью одного регулярного выражения.

4. Заключение

В этой статье мы рассмотрели, как проверить, содержит ли строка действительный номер телефона, используя различные регулярные выражения. Мы также научились использовать несколько регулярных выражений одновременно.

Как всегда, полный исходный код статьи доступен на GitHub.