Комплексное регулярное выражение для проверки номера телефона

839

Я пытаюсь собрать всеобъемлющее регулярное выражение для проверки номеров телефонов. В идеале он будет обрабатывать международные форматы, но он должен обрабатывать форматы США, в том числе следующие:

  • 1-234-567-8901
  • 1-234-567-8901 x1234
  • 1-234-567-8901 ext1234
  • 1 (234) 567-8901
  • 1.234.567.8901
  • 1/234/567/8901
  • 12345678901

Я отвечу своей текущей попыткой, но я надеюсь, что у кого-то есть что-то лучшее и/или более элегантное.

  • 1
    Попытка создать всеобъемлющее регулярное выражение с нуля, как правило, плохая идея, если у вас нет веских причин для его реализации. Вы находитесь в прямом контакте с SMSC или другим оборудованием, управляемым Telcom? Если это так, вы сможете получить от них такую информацию, связанную с проверкой.
  • 3
    Кстати, вы должны указать, какой язык вы используете. Не все движки регулярных выражений имеют одинаковый синтаксис.
Показать ещё 11 комментариев
Теги:
validation
phone-number

39 ответов

513
Лучший ответ

Лучшая опция... просто нарисуйте все незнаковые символы на входе (кроме знаков "x" и "ведущих" +), заботясь о том, что британская тенденция записывать числа в нестандартной форме +44 (0) ..., когда попросил использовать международный префикс (в этом конкретном случае вы должны полностью отказаться от (0)).

Затем вы получите значения, например:

 12345678901
 12345678901x1234
 345678901x1234
 12344678901
 12345678901
 12345678901
 12345678901
 +4112345678
 +441234567890

Затем, когда вы показываете, переформатируйте содержимое вашего сердца. например.

  1 (234) 567-8901
  1 (234) 567-8901 x1234
  • 34
    Код форматирования будет пустой тратой времени, если номера будут приходить из-за пределов США.
  • 0
    @Earwicker - согласился, что форматирование (если речь идет о международных #) должно быть достаточно умным, чтобы обрабатывать различные форматы ... например (0123) 456 7890 или +1 234 567-89-01. В зависимости от того, насколько сложным вы хотите его получить, должно быть что-то, что можно выяснить, исходя из количества цифр и того, какие первые несколько цифр.
Показать ещё 33 комментария
296

Оказалось, что для этого есть что-то вроде спецификации, по крайней мере для Северной Америки, называемой NANP.

Вам нужно точно указать, что вы хотите. Что такое правовые разделители? Пробелы, тире и периоды? Не допускается использование разделителя? Можно ли смешивать разделители (например, + 0.111-222.3333)? Как будут обрабатываться расширения (например, 111-222-3333 x 44444)? Как насчет специальных номеров, например 911? Является ли региональный код необязательным или обязательным?

Здесь регулярное выражение для 7 или 10-значного числа с допустимыми расширениями, разделителями являются пробелы, тире или периоды:

^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$
  • 7
    здесь это без секции расширения (я заставляю моих пользователей вводить ext в отдельном поле): ^ (?: (?: \ +? 1 \ s * (?: [.-] \ s *)?)? (? (\ S * ([2-9] 1 [02-9] | [2-9] [02-8] 1 | [2-9] [02-8] [02-9]) \ с *) | ([2-9] 1 [02-9] | [2-9] [02-8] 1 | [2-9] [02-8] [02-9])) \ S * (: [? .-] \ s *)) ([2-9] 1 [02-9] |? [2-9] [02-9] 1 | [2-9] [02-9] {2}) \ s * (?: [.-] \ S *)? ([0-9] {4}) $
  • 0
    Это хорошо сработало для меня. Мне нужно было обновить часть расширения, добавив косую черту перед знаком #, в противном случае он говорит, что оттуда есть комментарий
Показать ещё 7 комментариев
265
.*

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

Я также рассмотрел бы любое из следующих действий как допустимые записи на веб-сайте:

"123 456 7890 until 6pm, then 098 765 4321"  
"123 456 7890 or try my mobile on 098 765 4321"  
"ex-directory - mind your own business"
  • 184
    Я согласен с мнением здесь, но иногда приятно проводить проверку, когда телефонный номер фактически будет использоваться для чего-то важного в интересах пользователя . Лучший пример - авторизация кредитной карты для покупки. Если номер телефона указан неверно, аутентификация может быть неудачной.
  • 46
    Если пользователь не хочет вводить свой номер телефона, вы можете просто оставить поле необязательным, но стоит ли просить пользователя ввести действительный номер телефона, если он собирается его ввести?
Показать ещё 25 комментариев
144

Я также предложил бы посмотреть библиотеку Google libphonenumber. Я знаю, что это не регулярное выражение, но оно делает именно то, что вы хотите.

Например, он признает, что:

15555555555

является возможным числом, но не действительным числом. Он также поддерживает страны за пределами США.

Основные функциональные возможности:

  • Разбор/форматирование/подтверждение номеров телефонов для всех стран/регионов мира.
  • getNumberType - получает тип числа, основанного на самом номере; способные отличать фиксированную, мобильную, бесплатную, премиальную ставку, общую стоимость, VoIP и личные номера (когда это возможно).
  • isNumberMatch - получает уровень уверенности в том, могут ли два числа быть одинаковыми.
  • getExampleNumber/getExampleNumberByType - предоставляет действительные номера примеров для всех стран/регионов, с возможностью указать, какой тип номера номера телефона нужен.
  • isPossibleNumber - быстро угадывает, является ли число возможным номером звонка, используя только информацию о длине, намного быстрее, чем полная проверка.
  • isValidNumber - полная проверка номера телефона для региона с использованием информации о длине и префиксе.
  • AsYouTypeFormatter - форматирует телефонные номера "на лету", когда пользователи вводят каждую цифру.
  • findNumbers - находит числа в текстовом вводе.
  • PhoneNumberOfflineGeocoder - предоставляет географическую информацию, относящуюся к номеру телефона.

Примеры

Самая большая проблема с проверкой номера телефона - это очень культурно зависимая.

  • Америка
    • (408) 974–2042 является действительным номером США
    • (999) 974–2042 не является действительным номером США
  • Австралия
    • 0404 999 999 является действительным австралийским номером
    • (02) 9999 9999 также является действительным австралийским номером
    • (09) 9999 9999 не является действительным австралийским номером

Регулярное выражение прекрасно подходит для проверки формата номера телефона, но на самом деле не будет возможности проверить правильность номера телефона.

Я бы предложил пропустить простое регулярное выражение, чтобы проверить ваш номер телефона, и использовать библиотеку, такую как Google libphonenumber (ссылка на проект GitHub).

Представляем libphonenumber!

Используя один из ваших более сложных примеров, 1-234-567-8901 x1234, вы получаете следующие данные из libphonenumber (ссылка на онлайн-демонстрацию):

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     true

Formatting Results:

E164 format                    +12345678901
Original format                (234) 567-8901 ext. 123
National format                (234) 567-8901 ext. 123
International format           +1 234-567-8901 ext. 123
Out-of-country format from US  1 (234) 567-8901 ext. 123
Out-of-country format from CH  00 1 234-567-8901 ext. 123

Таким образом, вы не только узнаете, действительно ли номер телефона (какой он есть), но также вы получаете согласованное форматирование номера телефона в своем регионе.

В качестве бонуса libphonenumber имеет ряд наборов данных для проверки действительности номеров телефонов, поэтому проверка номера, такого как +61299999999 (международная версия (02) 9999 9999), возвращает в качестве действительного номера с форматированием:

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     true

Formatting Results

E164 format                    +61299999999
Original format                61 2 9999 9999
National format                (02) 9999 9999
International format           +61 2 9999 9999
Out-of-country format from US  011 61 2 9999 9999
Out-of-country format from CH  00 61 2 9999 9999

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

PhoneNumberOfflineGeocoder Results
Location        Australia

PhoneNumberToTimeZonesMapper Results
Time zone(s)    [Australia/Sydney]

Но недействительный австралийский телефонный номер ( (09) 9999 9999) возвращает, что это не действительный номер телефона.

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     false

В версии Google есть код для Java и Javascript, но люди также реализовали библиотеки для других языков, которые используют набор данных телефона i18n Google:

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

  • 0
    Отметив, что теперь есть также порт Go по адресу: github.com/ttacon/libphonenumber
  • 0
    При проверке, возможно ли это число, вам не нужно указывать код страны? Я использую версию PHP, и если я ввожу британское число, например (замените 0 действительными числами) 07700000000 я получу Missing or invalid default region. ошибка. Но если я укажу код страны, он пройдет.
Показать ещё 2 комментария
71

/^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$/i

Это соответствует:

 - (+351) 282 43 50 50
 - 90191919908
 - 555-8909
 - 001 6867684
 - 001 6867684x1
 - 1 (234) 567-8901
 - 1-234-567-8901 x1234
 - 1-234-567-8901 ext1234
 - 1-234 567.89/01 ext.1234
 - 1(234)5678901x1234
 - (123)8575973
 - (0055)(123)8575973

В $ n это экономит:

  1. Индикатор страны
  2. Номер телефона
  3. расширение

Вы можете протестировать его на https://www.regexpal.com/?fam=99127

  • 0
    В каком двигателе? В Javascript и PHP работает отлично.
  • 0
    Это было наиболее полное регулярное выражение, которое я видел. Это легко обойти, пока вы не удалите ^ и $ иначе я не смогу обойти это, используя [111] [111] [1111] или 111--111--1111 и т.п. (извините, удалил мой последний комментарий)
Показать ещё 12 комментариев
65

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

1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?

Здесь perl script, чтобы проверить его. Когда вы сопоставляете, $1 содержит код области, $2 и $3 содержат номер телефона, а $5 содержит расширение. Мой тест script загружает файл из Интернета и печатает в нем все номера телефонов.

#!/usr/bin/perl

my $us_phone_regex =
        '1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?';


my @tests =
(
"1-234-567-8901",
"1-234-567-8901 x1234",
"1-234-567-8901 ext1234",
"1 (234) 567-8901",
"1.234.567.8901",
"1/234/567/8901",
"12345678901",
"not a phone number"
);

foreach my $num (@tests)
{
        if( $num =~ m/$us_phone_regex/ )
        {
                print "match [$1-$2-$3]\n" if not defined $4;
                print "match [$1-$2-$3 $5]\n" if defined $4;
        }
        else
        {
                print "no match [$num]\n";
        }
}

#
# Extract all phone numbers from an arbitrary file.
#
my $external_filename =
        'http://web.textfiles.com/ezines/PHREAKSANDGEEKS/PnG-spring05.txt';
my @external_file = `curl $external_filename`;
foreach my $line (@external_file)
{
        if( $line =~ m/$us_phone_regex/ )
        {
                print "match $1 $2 $3\n";
        }
}

Edit:

Вы можете изменить \W * на \s *\W?\s * в регулярном выражении, чтобы немного подтянуть его. Я не думал о регулярном выражении с точки зрения, скажем, проверки ввода пользователя в форме при написании, но это изменение позволяет использовать регулярное выражение для этой цели.

'1?\s*\W?\s*([2-9][0-8][0-9])\s*\W?\s*([2-9][0-9]{2})\s*\W?\s*([0-9]{4})(\se?x?t?(\d*))?';
  • 2
    К вашему сведению, регулярное выражение также соответствует: (4570457-6789 что было бы довольно распространенной опечаткой. Группы совпадений также перекосились : rubular.com/r/TaTP0mHL5c
  • 0
    @SooDesuNe Prepending (^|[^\d\n]) (с включенным многострочным флагом) позволяет избежать общей проблемы, гарантируя, что ему не предшествует что-то числовое.
38

Я ответил на этот вопрос по другому вопросу SO, прежде чем принять решение включить мой ответ в качестве ответа на этот поток, потому что никто не обращался к тому, как требовать/не требовать элементов, просто раздавая регулярные выражения: Regex работает неправильно, сопоставляя неожиданные вещи

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

Быстрый лист обмана

  • Запустите выражение: /^
  • Если требуется пространство, используйте: [\s] или \s
  • Если вы хотите потребовать скобки, используйте: [(] и [)]. Использование \( и \) является уродливым и может сбить с толку.
  • Если вы хотите, чтобы что-то было необязательным, поместите ? после него
  • Если вы хотите дефис, просто введите - или [-]. Если вы не ставите его первым или последним в ряд других символов, вам может потребоваться его избежать: \-
  • Если вы хотите принять разные варианты в слоте, поместите скобки вокруг параметров: [-.\s] потребуется дефис, период или пробел. Значок вопроса после последней скобки сделает все из них необязательными для этого слота.
  • \d{3}: Требуется 3-значное число: 000-999. Сокращение для [0-9][0-9][0-9].
  • [2-9]: для этого слота требуется цифра 2-9.
  • (\+|1\s)?: Принять "плюс" или 1 и пробел (символ трубы, |, "или" ) и сделать его необязательным. Знак "плюс" должен быть экранирован.
  • Если вы хотите, чтобы определенные числа соответствовали слоту, введите их: [246] потребуется 2, 4 или 6. [77|78] потребуется 77 или 78.
  • $/: Завершить выражение
  • 1
    Это очень полезно, но я сомневаюсь и ищу выражение {min, max}. Вы можете помочь?
  • 0
    Если речь идет о единственной цифре (и вы можете сделать так, чтобы она соответствовала этому), см. Блок [2-9] который я поставил там. Это означает, что ваш минимум равен 2, а ваш максимум равен 9. Отрегулируйте соответственно.
26

Я написал самый простой (хотя мне не нужна точка в нем).

^([0-9\(\)\/\+ \-]*)$

Как упоминалось ниже, он проверяет только символы, а не его структуру/порядок

  • 1
    Не работал для меня
  • 36
    это проверяет тонны чисел, которые технически недействительны. как, "- + () () ()) ())))". Научитесь читать регулярные выражения, чтобы вы могли понять, что вы делаете.
Показать ещё 5 комментариев
21

Обратите внимание, что дескрипторы () не работают для стиля написания номеров Великобритании, которые являются общими: +44 (0) 1234 567890, что означает набрать международный номер:
+441234567890
или в Великобритании наберите 01234567890

18

Если вы просто хотите проверить, что у вас нет случайного мусора в поле (т.е. от спаммеров формы), это регулярное выражение должно делать красиво:

^[0-9+\(\)#\.\s\/ext-]+$

Обратите внимание, что у него нет каких-либо специальных правил для того, сколько цифр или какие числа действительны в этих цифрах, оно просто проверяет, что только цифры, скобки, тире, плюс, пробел, фунт, звездочка, период, запятая, или буквы e, x, t.

Он должен быть совместим с международными номерами и форматами локализации. Предусматриваете ли вы необходимость разрешать квадратные, кудрявые или угловые скобки для некоторых регионов? (в настоящее время они не включены).

Если вы хотите поддерживать правила на каждую цифру (например, в кодах и префиксах США (коды обмена), которые должны находиться в диапазоне от 200 до 999), удачи вам. Поддержание сложного набора правил, которое может быть устаревшим в любой момент в будущем любой страной мира, не выглядит забавным.

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

14

Просматривали ли вы RegExLib?

Ввод номера в США привел к появлению списка возможностей.

  • 8
    ... многие из которых имеют недостатки, естественно.
  • 2
    Это выглядит как отличный способ интегрировать неясные ошибки в ваш код.
12

Я нашел, что это работает очень хорошо:

^\(*\+*[1-9]{0,3}\)*-*[1-9]{0,3}[-. /]*\(*[2-9]\d{2}\)*[-. /]*\d{3}[-. /]*\d{4} *e*x*t*\.* *\d{0,4}$

Он работает для этих форматов:

1-234-567-8901
1-234-567-8901 x1234
1-234-567-8901 ext1234
1 (234) 567-8901
1.234.567.8901
1/234/567/8901
12345678901
1-234-567-8901 ext. 1234
(+351) 282 433 5050

Обязательно используйте глобальные и многострочные флаги, чтобы убедиться.

Ссылка: http://www.regexr.com/3bp4b

12

Моя попытка неограниченного регулярного выражения:

/^[+#*\(\)\[\]]*([0-9][ ext+-pw#*\(\)\[\]]*){6,45}$/

Принимает:

+(01) 123 (456) 789 ext555
123456
*44 123-456-789 [321]
123456
123456789012345678901234567890123456789012345
*****++[](][((( 123456tteexxttppww

Отклонение:

mob 07777 777777
1234 567 890 after 5pm
john smith
(empty)
1234567890123456789012345678901234567890123456
911

Это зависит от вас, чтобы дезинфицировать его для отображения. После проверки это может быть число.

11

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

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

Северная Америка проста, и для международных я предпочитаю использовать "идиоматический" шаблон, который охватывает способы, которыми люди указывают и запоминают их номера:

^((((\(\d{3}\))|(\d{3}-))\d{3}-\d{4})|(\+?\d{2}((-| )\d{1,8}){1,5}))(( x| ext)\d{1,5}){0,1}$

Североамериканский образец гарантирует, что если одна скобка включена, то и есть. Международные счета для необязательного первоначального "+" и кода страны. После этого вы находитесь в идиоме. Допустимые совпадения:

  • (xxx)xxx-xxxx
  • (xxx)-xxx-xxxx
  • (xxx)xxx-xxxx x123
  • 12 1234 123 1 x1111
  • 12 12 12 12 12
  • 12 1 1234 123456 x12345
  • +12 1234 1234
  • +12 12 12 1234
  • +12 1234 5678
  • +12 12345678

Это может быть предвзятым, поскольку мой опыт ограничен Северной Америкой, Европой и небольшим количеством Азии.

  • 0
    Я пытался реализовать вышеупомянутое в моем сценарии проверки JavaScript, но получаю invalid quantifier ошибку invalid quantifier . Есть идеи, что я делаю не так?
  • 0
    Я бы добавил тривиальный случай, когда телефон указан без символов, но, возможно, пробелы и код страны, в Европе типично для местных и мобильных номеров: 676412342, 676 46 32 12, 676 463 212
10

Это простой шаблон регулярного выражения для филиппинских номеров мобильных телефонов:

((\+[0-9]{2})|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}

или

((\+63)|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}

будет соответствовать этим:

+63.917.123.4567  
+63-917-123-4567  
+63 917 123 4567  
+639171234567  
09171234567  

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

Протестируйте его здесь: http://refiddle.com/1ox

  • 0
    Благодарю. Как насчет стационарных номеров с кодом города, например 028231234? Мне интересно, если коды городов состоят только из 2-3 цифр и им всегда предшествует 0?
9

Чувство моего чувства усиливается количеством ответов на эту тему - что существует практически бесконечное количество решений этой проблемы, ни одна из которых не будет элегантной.

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

На мой взгляд, самым элегантным решением является проверка минимальной длины, не более того.

  • 0
    После нескольких попыток и изучения существующих данных и отзывов пользователей я склонен согласиться ...
8

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

Следующее регулярное выражение будет использовать широко используемые комбинации чисел и символов в различных форматах глобальных телефонных номеров:

/^\s*(?:\+?(\d{1,3}))?([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/gm

Positive:
+42 555.123.4567
+ 1 (800) -123-4567
+7 555 1234567
+7 (926) 1234567
(926) 1234567
+79261234567
926 1234567
9261234567
1234567
123-4567
123-89-01
495 1234567
469 123 45 67
89261234567
8 (926) 1234567
926.123.4567
415-555-1234
650-555-2345
(416)555-3456
202 555 4567
4035555678
1 416 555 9292

Negative:
926 3 4
8 800 600-APPLE

Исходный источник: http://www.regexr.com/38pvb

  • 0
    Это имеет ограниченную поддержку расширений. Он соответствует «616-555-1234 x567», но не «616-555-1234 доб. 567».
  • 1
    Неверно положительный, например, "------- ((((((55555555" или "99999999999999999999999")
Показать ещё 1 комментарий
8

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

Вот то, что я недавно использовал для клиентского проекта, где нам пришлось преобразовать все телефонные номера в любом формате в tel: links.

До сих пор он работал со всем, что они бросили на него, но если возникнут ошибки, я обновлю этот ответ.

Regex:

/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/

PHP-функция для замены всех телефонных номеров на tel: links (в случае, если кому-то интересно):

function phoneToTel($number) {
    $return = preg_replace('/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/', '<a href="tel:$1$3$4$5">$1 ($3) $4-$5</a>', $number); // includes international
    return $return;
}
  • 0
    Это регулярное выражение соответствует +1 1234562222222222222222222222 .
  • 0
    почему бы просто не вернуться?
8

Вам будет сложно работать с международными номерами с одним/простым регулярным выражением, см. этот пост о трудностях международного (и даже северного) телефона числа.

Вам нужно проанализировать первые несколько цифр, чтобы определить, что такое код страны, а затем действовать по-разному в зависимости от страны.

Помимо этого - список, который вы указали, не включает другой общий формат США - оставляя начальный 1. Большинство сотовых телефонов в США не требуют этого, и оно начнет дезориентировать молодое поколение, если они не будут набирается на международном уровне.

Вы правильно определили, что это сложная проблема...

-Adam

  • 0
    Не предлагаемое решение. ЭТО ВОЗМОЖНО. То, что это сложно или сложно, не означает, что вы должны просто поднять руки вверх.
7

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

^\d?(?:(?:[\+]?(?:[\d]{1,3}(?:[ ]+|[\-.])))?[(]?(?:[\d]{3})[\-/)]?(?:[ ]+)?)?(?:[a-zA-Z2-9][a-zA-Z0-9 \-.]{6,})(?:(?:[ ]+|[xX]|(i:ext[\.]?)){1,2}(?:[\d]{1,5}))?$
6

Я верю Number:: Phone:: US и Regexp:: Общие (в частности, источник Regexp:: Common:: URI:: RFC2806). Могут помочь модули Perl.

Вероятно, вопрос должен быть определен более подробно, чтобы объяснить цель проверки чисел. Например, 911 является допустимым числом в США, но 911x не имеет значения x. Это так, что телефонная компания может рассчитать, когда вы закончите набор. Существует несколько вариантов этой проблемы. Но ваше регулярное выражение не проверяет часть кода области, поэтому это не вызывает беспокойства.

Как и при проверке адресов электронной почты, даже если у вас есть действительный результат, вы не можете знать, назначен ли он кому-то, пока вы не попробуете его.

Если вы пытаетесь проверить ввод пользователя, почему бы не нормализовать результат и не сделать с ним? Если пользователь вводит номер, который вы не можете распознать как действительный номер, сохраните его как введенный или вычеркнутый недопустимый символ. Number:: Phone:: Normalize Модуль Perl может стать источником вдохновения.

  • 0
    Я собираюсь выйти на конечность и сказать, что использование 911 в качестве номера телефона, вероятно, является плохой идеей почти во всех приложениях этого регулярного выражения. Хороший улов, хотя.
4

Сделайте замену на форматирование символов, затем проверьте оставшиеся для действительности телефона. В PHP,

 $replace = array( ' ', '-', '/', '(', ')', ',', '.' ); //etc; as needed
 preg_match( '/1?[0-9]{10}((ext|x)[0-9]{1,4})?/i', str_replace( $replace, '', $phone_num );

Ломать сложное регулярное выражение, подобное этому, может быть столь же эффективным, но гораздо более простым.

4

Я работаю в компании, занимающейся исследованиями рынка, и мы должны фильтровать эти типы ввода все время. Вы слишком усложняете это. Просто разделите не-буквенно-цифровые символы и посмотрите, есть ли расширение.

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

  • 0
    Проверка? 123% $) *% () $ * () # 456 * () * $ # (* (# $ @ 8908 будет соответствовать предложенному вами решению).
  • 1
    @PlexQ 555-123-1234, 07777777777, 90210, 01.01.1901 - пользователи изобретательны в том, чтобы утрамбовывать мусор посредством проверки. Лучше не ставить галочку на тех, кто действительно имеет какие-то странные данные, используя чрезмерно ограничительную валидацию и сообщая им, что они не правы.
3

Здесь хорошо работает JavaScript. Это в строке, потому что то, что ожидал виджет Dojo.

Он соответствует десятизначному номеру NANP Северной Америки с дополнительным расширением. Пробелы, тире и периоды являются принятыми разделителями.

"^(\\(?\\d\\d\\d\\)?)( |-|\\.)?\\d\\d\\d( |-|\\.)?\\d{4,4}(( |-|\\.)?[ext\\.]+ ?\\d+)?$"
3

Вероятно, вам лучше использовать Masked Input для этого. Таким образом, пользователи могут ТОЛЬКО вводить цифры, и вы можете форматировать, как вы считаете нужным. Я не уверен, что это для веб-приложения, но если есть плагин jQuery с очень кликом, который предлагает некоторые варианты для этого.

http://digitalbush.com/projects/masked-input-plugin/

Они даже переходят к тому, как маскировать номера телефонов в своем учебнике.

3

Я нашел это что-то интересное. Я не тестировал его, но похоже, что он будет работать

<?php
/*
string validate_telephone_number (string $number, array $formats)
*/

function validate_telephone_number($number, $formats)
{
$format = trim(ereg_replace("[0-9]", "#", $number));

return (in_array($format, $formats)) ? true : false;
}

/* Usage Examples */

// List of possible formats: You can add new formats or modify the existing ones

$formats = array('###-###-####', '####-###-###',
                 '(###) ###-###', '####-####-####',
                 '##-###-####-####', '####-####', '###-###-###',
                 '#####-###-###', '##########');

$number = '08008-555-555';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '123-555-555';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '1800-1234-5678';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '(800) 555-123';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}

echo "<br />";

$number = '1234567890';

if(validate_telephone_number($number, $formats))
{
echo $number.' is a valid phone number.';
}
?>
  • 4
    Ваше сообщение указывает на то, что вы не написали этот код. Не могли бы вы привести источник, пожалуйста?
  • 0
    bitrepository.com/how-to-validate-a-telephone-number.html выглядит как источник.
3

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

В худшем случае, если пользователю пришлось вытащить неформатированный номер из файла XML, они все равно просто наберут цифры на телефонную номерную табличку 012345678x5, и не повод для ее сохранения. Такой RegEx выйдет что-то вроде этого для меня:

\d+ ?\w{0,9} ?\d+
  • 01234467 extension 123456
  • 01234567x123456
  • 01234567890
2

Для всех, кто заинтересован в том, чтобы делать что-то подобное с номерами мобильных телефонов Ирландии, здесь можно сделать простой способ:

http://ilovenicii.com/?p=87

PHP


<?php
$pattern = "/^(083|086|085|086|087)\d{7}$/";
$phone = "087343266";

if (preg_match($pattern,$phone)) echo "Match";
else echo "Not match";

В этой связи также есть решение JQuery.

EDIT:

Решение jQuery:

    $(function(){
    //original field values
    var field_values = {
            //id        :  value
            'url'       : 'url',
            'yourname'  : 'yourname',
            'email'     : 'email',
            'phone'     : 'phone'
    };

        var url =$("input#url").val();
        var yourname =$("input#yourname").val();
        var email =$("input#email").val();
        var phone =$("input#phone").val();


    //inputfocus
    $('input#url').inputfocus({ value: field_values['url'] });
    $('input#yourname').inputfocus({ value: field_values['yourname'] });
    $('input#email').inputfocus({ value: field_values['email'] }); 
    $('input#phone').inputfocus({ value: field_values['phone'] });



    //reset progress bar
    $('#progress').css('width','0');
    $('#progress_text').html('0% Complete');

    //first_step
    $('form').submit(function(){ return false; });
    $('#submit_first').click(function(){
        //remove classes
        $('#first_step input').removeClass('error').removeClass('valid');

        //ckeck if inputs aren't empty
        var fields = $('#first_step input[type=text]');
        var error = 0;
        fields.each(function(){
            var value = $(this).val();
            if( value.length<12 || value==field_values[$(this).attr('id')] ) {
                $(this).addClass('error');
                $(this).effect("shake", { times:3 }, 50);

                error++;
            } else {
                $(this).addClass('valid');
            }
        });        

        if(!error) {
            if( $('#password').val() != $('#cpassword').val() ) {
                    $('#first_step input[type=password]').each(function(){
                        $(this).removeClass('valid').addClass('error');
                        $(this).effect("shake", { times:3 }, 50);
                    });

                    return false;
            } else {   
                //update progress bar
                $('#progress_text').html('33% Complete');
                $('#progress').css('width','113px');

                //slide steps
                $('#first_step').slideUp();
                $('#second_step').slideDown();     
            }               
        } else return false;
    });

    //second section
    $('#submit_second').click(function(){
        //remove classes
        $('#second_step input').removeClass('error').removeClass('valid');

        var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;  
        var fields = $('#second_step input[type=text]');
        var error = 0;
        fields.each(function(){
            var value = $(this).val();
            if( value.length<1 || value==field_values[$(this).attr('id')] || ( $(this).attr('id')=='email' && !emailPattern.test(value) ) ) {
                $(this).addClass('error');
                $(this).effect("shake", { times:3 }, 50);

                error++;
            } else {
                $(this).addClass('valid');
            }


        function validatePhone(phone) {
        var a = document.getElementById(phone).value;
        var filter = /^[0-9-+]+$/;
            if (filter.test(a)) {
                return true;
            }
            else {
                return false;
            }
        }

        $('#phone').blur(function(e) {
            if (validatePhone('txtPhone')) {
                $('#spnPhoneStatus').html('Valid');
                $('#spnPhoneStatus').css('color', 'green');
            }
            else {
                $('#spnPhoneStatus').html('Invalid');
            $('#spnPhoneStatus').css('color', 'red');
            }
        });

     });

        if(!error) {
                //update progress bar
                $('#progress_text').html('66% Complete');
                $('#progress').css('width','226px');

                //slide steps
                $('#second_step').slideUp();
                $('#fourth_step').slideDown();     
        } else return false;

    });


    $('#submit_second').click(function(){
        //update progress bar
        $('#progress_text').html('100% Complete');
        $('#progress').css('width','339px');

        //prepare the fourth step
        var fields = new Array(
            $('#url').val(),
            $('#yourname').val(),
            $('#email').val(),
            $('#phone').val()

        );
        var tr = $('#fourth_step tr');
        tr.each(function(){
            //alert( fields[$(this).index()] )
            $(this).children('td:nth-child(2)').html(fields[$(this).index()]);
        });

        //slide steps
        $('#third_step').slideUp();
        $('#fourth_step').slideDown();            
    });


    $('#submit_fourth').click(function(){

        url =$("input#url").val();
        yourname =$("input#yourname").val();
        email =$("input#email").val();
        phone =$("input#phone").val();

        //send information to server
        var dataString = 'url='+ url + '&yourname=' + yourname + '&email=' + email + '&phone=' + phone;  



        alert (dataString);//return false;  
            $.ajax({  
                type: "POST",  
                url: "http://clients.socialnetworkingsolutions.com/infobox/contact/",  
                data: "url="+url+"&yourname="+yourname+"&email="+email+'&phone=' + phone,
                cache: false,
                success: function(data) {  
                    console.log("form submitted");
                    alert("success");
                }
                });  
        return false;

   });


    //back button
    $('.back').click(function(){
        var container = $(this).parent('div'),
        previous  = container.prev();

        switch(previous.attr('id')) {
            case 'first_step' : $('#progress_text').html('0% Complete');
                  $('#progress').css('width','0px');
                       break;
            case 'second_step': $('#progress_text').html('33% Complete');
                  $('#progress').css('width','113px');
                       break;

            case 'third_step' : $('#progress_text').html('66% Complete');
                  $('#progress').css('width','226px');
                       break;

        default: break;
    }

    $(container).slideUp();
    $(previous).slideDown();
});


});

Источник.

2
    pattern="^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$" 
    validateat="onsubmit"

Должен закончиться цифрой, может начинаться с (или + или цифры, и может содержать + - (или)

2

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

Несколько простых выражений perl могут быть:

@f = /(\d+)/g;
tr/0-9//dc;

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

Можно ли беспокоиться о том, что может потребоваться пауза, а затем ввести еще несколько клавиш? Или что-то вроде 555-1212 (дождитесь звукового сигнала) 123?

1

Поскольку в этом сообщении нет языкового тега, я дам решение regex используемое в python.

Само выражение:

1[\s./-]?\(?[\d]+\)?[\s./-]?[\d]+[-/.]?[\d]+\s?[\d]+

При использовании в python:

import re

phonelist ="1-234-567-8901,1-234-567-8901 1234,1-234-567-8901 1234,1 (234) 567-8901,1.234.567.8901,1/234/567/8901,12345678901"

phonenumber = '\n'.join([phone for phone in re.findall(r'1[\s./-]?\(?[\d]+\)?[\s./-]?[\d]+[-/.]?[\d]+\s?[\d]+' ,phonelist)])
print(phonenumber)

Вывод:

1-234-567-8901
1-234-567-8901 1234
1-234-567-8901 1234
1 (234) 567-8901
1.234.567.8901
1/234/567/8901
12345678901
1

Найти String regex = "^\\+(?:[0-9] ?){6,14}[0-9]$";

полезно для международных номеров.

1

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

Вам лучше использовать службу, например numverify.com, они предлагают бесплатный JSON API для проверки международного номера телефона, а также вы получите некоторые полезные сведения о стране, местоположении, перевозчике и типе линии с каждым запросом.

1

Рабочий пример для Турции, просто измените

d{9}

в соответствии с вашими потребностями и начать использовать его.

function validateMobile($phone)
{
    $pattern = "/^(05)\d{9}$/";
    if (!preg_match($pattern, $phone))
    {
        return false;
    }
    return true;
}

$phone = "0532486061";

if(!validateMobile($phone))
{
    echo 'Incorrect Mobile Number!';
}

$phone = "05324860614";
if(validateMobile($phone))
{
    echo 'Correct Mobile Number!';
}
1

Я бы не рекомендовал использовать регулярное выражение для этого.

Как и главный ответ, уберите все уродство с номера телефона, так что вы останетесь с строкой числовых символов с 'x', если предусмотрены расширения.

В Python:

Примечание. BAD_AREA_CODES происходит из текстового файла , который вы можете получить в Интернете.

BAD_AREA_CODES = open('badareacodes.txt', 'r').read().split('\n')

def is_valid_phone(phone_number, country_code='US'):
    """for now, only US codes are handled"""
    if country_code:
        country_code = country_code.upper()

    #drop everything except 0-9 and 'x'
    phone_number = filter(lambda n: n.isdigit() or n == 'x', phone_number)

    ext = None
    check_ext = phone_number.split('x')
    if len(check_ext) > 1:
        #there an extension. Check for errors.
        if len(check_ext) > 2:
            return False
        phone_number, ext = check_ext

    #we only accept 10 digit phone numbers.
    if len(phone_number) == 11 and phone_number[0] == '1':
        #international code
        phone_number = phone_number[1:]
    if len(phone_number) != 10:
        return False

    #area_code: XXXxxxxxxx 
    #head:      xxxXXXxxxx
    #tail:      xxxxxxXXXX
    area_code = phone_number[ :3]
    head      = phone_number[3:6]
    tail      = phone_number[6: ]

    if area_code in BAD_AREA_CODES:
        return False
    if head[0] == '1':
        return False
    if head[1:] == '11':
        return False

    #any other ideas?
    return True

Это довольно много. Это не регулярное выражение, но оно легко сопоставляется с другими языками.

1

Возможно ли, чтобы для дисплея отображалось 4 отдельных поля (код зоны, трехзначный префикс, 4-значная часть, расширение), чтобы они могли вводить каждую часть адреса отдельно, и вы можете проверить каждую часть отдельно? Таким образом, вы можете не только упростить верификацию, но и сохранить ваши номера телефонов в более согласованном формате в базе данных.

  • 0
    Однако, если вы решите пойти по этому пути, имейте в виду, что это не будет работать за пределами США. Нет возможности ввести добавочный номер страны, и, например, в Германии есть коды зоны переменной длины (от 2 до 4 цифр, плюс начальный ноль, если вы набираете номер из Германии, который пропускается, если перед вами стоит код страны). ).
0

Попробуйте это (это для проверки числа мобильных телефонов в Индии):

if (!phoneNumber.matches("^[6-9]\\d{9}$")) {
  return false;
} else {
  return true;
}
  • 0
    Почему бы просто не вернуть результат matches ?
0

Примечание. Для ввода номера мобильного телефона США в любом формате требуется дополнительный параметр и, при необходимости, принимает второй параметр - установите значение true, если вы хотите, чтобы выходной номер мобильного телефона выглядел красиво. Если предоставленное число не является мобильным номером, оно просто возвращает false. Если обнаружен номер мобильного телефона, он возвращает все дезинфицированное число вместо истинного.

    function isValidMobile(num,format) {
        if (!format) format=false
        var m1 = /^(\W|^)[(]{0,1}\d{3}[)]{0,1}[.]{0,1}[\s-]{0,1}\d{3}[\s-]{0,1}[\s.]{0,1}\d{4}(\W|$)/
        if(!m1.test(num)) {
           return false
        }
        num = num.replace(/ /g,'').replace(/\./g,'').replace(/-/g,'').replace(/\(/g,'').replace(/\)/g,'').replace(/\[/g,'').replace(/\]/g,'').replace(/\+/g,'').replace(/\~/g,'').replace(/\{/g,'').replace(/\*/g,'').replace(/\}/g,'')
        if ((num.length < 10) || (num.length > 11) || (num.substring(0,1)=='0') || (num.substring(1,1)=='0') || ((num.length==10)&&(num.substring(0,1)=='1'))||((num.length==11)&&(num.substring(0,1)!='1'))) return false;
        num = (num.length == 11) ? num : ('1' + num);   
        if ((num.length == 11) && (num.substring(0,1) == "1")) {
            if (format===true) {
               return '(' + num.substr(1,3) + ') ' + num.substr(4,3) + '-' + num.substr(7,4)
            } else {
               return num
            }
        } else {
            return false;
        }
    }
-4
/\b(\d{3}[^\d]{0,2}\d{3}[^\d]{0,2}\d{4})\b/

Ещё вопросы

Сообщество Overcoder
Наверх
Меню