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

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

  • 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

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

Этот ответ был добавлен в Часто задаваемые вопросы о регулярных выражениях при переполнении стека в разделе «Общие задачи проверки».

aliteralmind 10.04.2014 05:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
959
1
992 861
43
Перейти к ответу Данный вопрос помечен как решенный

Ответы 43

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

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

Работал как шарм! Спасибо, что поделился

KdPisda 29.01.2021 17:55

Вы видели RegExLib?

Ввод номера телефона в США вернул целый список возможностей.

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

Tom Lord 26.10.2016 12:25

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

mickmackusa 31.07.2020 23:24

Оказывается, для этого есть что-то вроде спецификации, по крайней мере для Северной Америки, которая называется 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+))?$

здесь он без секции расширений (я заставляю пользователей вводить ext в отдельное поле): ^ (?: (?: \ +? 1 \ s * (?: [.-] \ s *)?)? (? : (\ s * ([2-9] 1 [02-9] | [2-9] [0‌ 2-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}) $

aarona 04.05.2010 08:37

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

Brian Surowiec 20.08.2010 20:58

А как насчет добавления "(" и ")" к этому списку разделителей?

Jeremy Ricketts 01.09.2010 07:23

Вот версия, которая соответствует только 10-значным телефонным номерам (а не 7-значным, как 843-1212): /(?:(?:\+?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})/

Brian Armstrong 07.09.2010 23:32

10 цифр принимает () вокруг кода города и не позволяет использовать код страны перед 1 как (?:(?:(\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}).

Brooke. 09.01.2011 08:09

@StevenSoroka Последние два года рядом со мной на столе лежит книга Джеффри Фридла, поскольку регулярные выражения - основная часть моей работы. Чтобы по-настоящему понять регулярные выражения, нужно время. Иногда читатели этого сайта просто ищут существующее решение, а не пишут собственное, особенно в доменах с большим количеством угловых случаев, таких как представление телефонных номеров.

Justin R. 29.03.2013 01:06

@ fatcat1111 Я понимаю это, но большинство ответов здесь относятся к разовым регулярным выражениям типа «я тоже», которые, вероятно, не подходят ни для одного из ваших угловых случаев. Затем они попадают на все веб-сайты, которые я пытаюсь использовать, и я не могу ввести свой почтовый индекс, номер телефона или адрес электронной почты, потому что кто-то использовал недолговечное регулярное выражение (например: + - допустимый символ в адресах электронной почты. ). Лучшие ответы на этой странице указывают пользователям на библиотеки, а не на нарисованные на салфетке регулярные выражения.

Steven Soroka 06.04.2013 01:49

Будьте осторожны и проверяйте наличие неразрывных пробелов при копировании этих выражений.

Nate Glenn 17.12.2015 05:47

Интересно, изменилось ли что-то с тех пор, как вы впервые разместили это? Он не соответствует хотя бы одному допустимому коду города: 410 (Мэриленд). 410 - это упомянул в статье Википедии, на которую вы ссылаетесь, но 410 находился в обслуживании с 1991 года.

ThisSuitIsBlackNot 17.05.2016 01:13

Похоже, это работает с каждым сценарием, который я использовал. Я даже ввел неверный код области, например, код области, который начинается с 1, недействителен, и он его поймал. AAA +++ Perfection для телефонных номеров в США ..

Switch 16.04.2019 18:44

Пример того, где это регулярное выражение не работает: 866-411-1234 (потому что он не разрешает обмен 411 в соответствии с правилами NANPA, но это нормально для номеров 8xx). regex101.com/r/3DSYIr/1

drew010 10.03.2020 00:37
Ответ принят как подходящий

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

Тогда вы получите такие значения, как:

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

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

  1 (234) 567-8901
  1 (234) 567-8901 x1234

Код форматирования будет пустой тратой времени, если числам разрешено поступать из-за пределов США.

Daniel Earwicker 21.07.2009 16:13

@Earwicker - согласился, что форматирование (при работе с международными #) должно быть достаточно умным, чтобы обрабатывать различные форматы ... например. (0123) 456 7890 или +1 234 567-89-01. В зависимости от того, насколько сложно вы хотите получить, это должно быть что-то, что можно вычислить на основе количества цифр и того, каковы первые несколько цифр.

scunliffe 21.07.2009 17:36

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

Hugh Jeffner 29.07.2010 17:40

string.replace ("[^ \ d +! x]", "")

Joel McBeth 06.12.2010 22:51

jcmcbeth, почему !x часть? Кажется, этого достаточно: [^\d+]rubular.com/r/aj32fRSSGK

Danilo Bargen 29.01.2011 01:09

@danilo -! x предназначен для предотвращения удаления любого символа «x», чтобы можно было отделить расширения.

cdeszaq 28.02.2011 19:53

Учитывая, что вопрос был о валидации - это действительно плохой ответ.

PlexQ 30.03.2012 21:12

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

scunliffe 31.03.2012 00:19

Для других, кто может использовать вышеупомянутый [^\d+!x] - восклицательный знак не нужен. Просто используйте [^\d+x]. См. stackoverflow.com/questions/10340336/….

Dan Nissenbaum 27.04.2012 01:18

@Raymond, вы можете использовать $justDigitsOrPlusOrX = preg_replace("/[^\d+x]/", "", $phoneNum);, чтобы удалить все символы, которые вам не нужны ... затем проверьте оставшиеся (при необходимости)

scunliffe 04.07.2012 23:21

Это прекрасно работает, за исключением чисел вроде 1-800-CALL-NOW?

Swanand 15.02.2013 10:40

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

scunliffe 15.02.2013 18:32

Улучшение Regex выше: /[^\d+x]|x(?=[^x]*x)/gi Предотвращает множественные x (использует последний x в строке)

Albert Bori 14.05.2013 00:37

Это хорошо, но не отвечает на поставленный вопрос, в котором явно запрашивается решение RegEx.

Kehlan Krumme 09.08.2013 21:53

@nashwan, вы читали статью, указанную в первом комментарии, добавленном Николасом Трандемом. Плакат с исходным вопросом? Иногда (как вы можете видеть, как проголосовало сообщество), даже если есть решение использовать регулярное выражение из 261 символа, которое обрабатывает множество сценариев ... попытка атаковать проблему другим способом - это на самом деле ответ, который вы хотите. Обратите внимание, что ответ Дэйва Кирби также предлагает не использовать строгое регулярное выражение ... также набирает (ATM 79 голосов)

scunliffe 28.08.2013 01:10

@Swanand Это мило, когда люди объясняют вещи в буквенных обозначениях, которые есть на большинстве телефонных клавиатур, но в стандартах это не поощряется. tools.ietf.org/html/rfc3966#section-5.1.2

ekillaby 17.10.2013 06:12

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

Jack Holt 26.11.2013 20:39

Я должен пояснить, что я буду «хранить» чистое значение и только «украшать» его по мере необходимости для отображения позже.

scunliffe 26.11.2013 23:43

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

alastair 01.04.2014 15:19

Да, проверка или форматирование телефонных номеров - не лучшая идея. Ниже приведены действительные номера телефонов в Германии: +49 (0) 89 12345, +49 (0) 6221 1234. Если вы находитесь в Германии, набирайте их как 089 12345 или 06221 1234, но, например, В Швейцарии это будет 0049 89 12345 или 0049 6221 1234. Это похоже на случай Великобритании, но наши коды городов не имеют фиксированной длины. Если у вас нет списка, вы не сможете правильно отформатировать числа.

uliwitness 01.04.2014 17:03

Как, черт возьми, этот ответ получил столько голосов? Это ничего не подтверждать. Что еще хуже, все остальные вопросы о проверке номера телефона ссылаются на этот ...

jlars62 19.06.2014 22:37

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

totallyNotLizards 26.06.2014 19:41

@configurator Ну, телефонные коды страны имеют свойство префикса, поэтому ваш пример (4 (420) 778-457800), если 4 - это код страны, а 420 - код области / города) не может быть реальным числом, однако вы указали, что знак "+" важен для обозначения того, являются ли первые цифры кодом страны. Возможно, лучшим примером будет

Peyton 04.07.2014 21:36

Это работает, но добавляет сложности в логику.

JohnMerlino 15.08.2014 22:32

Не использует регулярные выражения. +1

John Shedletsky 01.05.2015 04:25

См. Также: technet.microsoft.com/en-us/library/cc728034(v=ws.10).aspx При использовании TAPI для набора номера в окнах это может помочь.

Ben 08.09.2015 12:31

Я создал публичная сущность, предоставляющий функцию ES6, основанную на регулярном выражении @AlbertBori. Отзывы приветствуются.

Josh Habdas 10.01.2016 02:24

Номера Великобритании (+44) должны содержать 10 цифр после 0 / + 44. например 01234 567 890

mwfearnley 10.03.2016 13:46

@mwfearnley Не все есть с 9 и 7 (также бесплатные с 9 и 7) en.wikipedia.org/wiki/Telephone_numbers_in_the_United_Kingdo‌ м и в живой памяти длина изменилась

mmmmmm 22.03.2016 01:00

Стою исправлюсь .. Я достаточно взрослый, чтобы помнить смену - жил в 0234 году :)

mwfearnley 23.03.2016 01:06

Я размышляю: «из-за британской тенденции писать числа в нестандартной форме +44 (0)» Если это склонность многих людей, разве это не стандарт? (и чертовски раздражает, даже если я делаю это сам).

Jmons 02.05.2017 21:06

как это могло быть подтверждено как лучший ответ честно

fdsfdsfdsfds 11.12.2017 12:26

Неприемлемо, что, если вы не контролируете ввод? это не решает вопрос.

Leo Gurdian 27.01.2018 02:33

Это отличный ответ. Это показывает, что вы должны преобразовать в целое число, а затем проверить который (предположительно, используя простой алгоритм). Эта часть подразумевается или, по крайней мере, кажется мне очевидной. Проверять номер телефона с помощью регулярного выражения на лету - это безумие. Кроме того ... что нужно проверить в первую очередь? Что это настоящий номер телефона? Почему? Если пользователь предоставляет неверный номер телефона, это их проблема.

user428517 18.04.2018 00:23

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

RisingSun 28.01.2020 20:18

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

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

Проверка? 123% $) *% () $ * () # 456 * () * $ # (* (# $ @ 8908 будет соответствовать вашему предлагаемому решению.

PlexQ 30.03.2012 21:17

@PlexQ 555-123-1234, 07777777777, 90210, 01.01.1901 - пользователи изобретательны в том, чтобы забивать мусор посредством валидации. Лучше не ставить галочку перед теми, у кого действительно есть какие-то странные данные, используя чрезмерно ограничительную проверку и сообщая им, что они неправы.

ReactiveRaven 29.04.2012 07:19

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

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

uliwitness 01.04.2014 17:12

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

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

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

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

-Адам

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

Eric Hodonsky 29.03.2017 19:14

Я считаю, что модули Perl Номер :: Телефон :: США и Regexp :: Common (особенно источник Regexp :: Common :: URI :: RFC2806) могут помочь.

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

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

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

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

Nicholas Flynt 11.07.2012 00:29

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

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

Вот скрипт на Perl для его проверки. При совпадении $ 1 содержит код города, $ 2 и $ 3 - номер телефона, а $ 5 - расширение. Мой тестовый сценарий загружает файл из Интернета и печатает в нем все телефонные номера.

#!/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 [--]\n" if not defined ;
                print "match [-- ]\n" if defined ;
        }
        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   \n";
        }
}

Редактировать:

Вы можете изменить \ 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*))?';

К вашему сведению, регулярное выражение также соответствует: (4570457-6789, что было бы довольно распространенной опечаткой. Группы соответствий тоже искажаются: rubular.com/r/TaTP0mHL5c

SooDesuNe 20.02.2013 23:16

@SooDesuNe Добавление (^|[^\d\n]) (с включенным многострочным флагом) позволяет избежать общей проблемы, гарантируя, что ей не предшествует что-то числовое.

btown 23.03.2017 22:32

Обратите внимание, что это ориентировано на Северную Америку - в нем отсутствует "44 7911 123456".

Ben Wheeler 25.03.2020 19:40

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

Вот пара простых выражений Perl:

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

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

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

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

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

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

^((((\(\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

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

Я пытался реализовать вышеизложенное в моем сценарии проверки javascript, но продолжаю получать ошибку invalid quantifier. Есть идеи о том, что я делаю неправильно?

Jannis 18.10.2010 00:07

Я бы добавил тривиальный случай, когда телефон указан без символов, но, возможно, с пробелами и кодом страны, в Европе это типично для местных и мобильных номеров: 676412342, 676 46 32 12, 676463212

rupps 20.04.2015 02:12

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

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

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

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

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

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

.*

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

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

"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"

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

Pointy 10.11.2010 21:21

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

Joel McBeth 06.12.2010 22:41

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

Ben McIntyre 23.02.2011 03:09

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

Benjol 01.03.2011 15:14

@Benjol да, это правда - на мое личное мнение, вероятно, влияет тот факт, что на одном из моих ноутбуков есть липкая клавиша "5" :-)

Pointy 01.03.2011 15:52

Я согласен с точки зрения удобства использования, но разрешение произвольного ввода может подвергнуть ваш веб-сайт атакам с использованием межсайтовых сценариев (XSS). Злоумышленник может внедрить JavaScript в строку вашего номера телефона произвольной формы.

Chris Peterson 02.04.2011 02:37

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

PlexQ 30.03.2012 21:14

Обычно я склоняюсь к такому образу мышления с пользовательским опытом. Действительный номер телефона в США состоит из 10 цифр: ^(.*\d.*){10,}$. Это позволяет вводить его любым удобным для пользователя способом. Затем на серверной части удалите недопустимые символы.

Cory Mawhorter 28.09.2012 23:35

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

Alex B 16.11.2012 10:40

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

Pointy 16.11.2012 17:42

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

Jason 22.01.2013 23:33

Верно, но тогда вы могли бы просто сделать что-нибудь вроде «когда не пусто, проверить». Что-то вроде if (!empty($telephone) && !validation_function($telephone)) { //throw_error }, тогда вы можете НЕ вводить свой номер.

user2069217 03.09.2013 18:38

Здорово. Мой номер телефона - 1 'ИЛИ 1 = 1 - ЗАПРЕЩЕНО. См. xkcd.com/327 и owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005).

Aaron Newton 19.09.2013 12:31

Ответ содержит глубочайшую мудрость.

Ziggy 08.01.2014 18:15

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

Evan Donovan 24.01.2014 21:05

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

mmmmmm 10.04.2014 15:49

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

Evan Donovan 11.04.2014 19:15

Этот ответ не отвечает на вопрос - скорее, он просто способствует непереносимости форм, то есть уже присуще всем нам.

darkheartfelt 08.01.2015 02:09

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

Willem Van Onsem 18.02.2015 20:21

@CommuSoft, это правда. Однако лучшим заявлением может быть не полагайтесь исключительно на регулярное выражение для предотвращения SQL-инъекции. Я бы все равно сказал, что имеет смысл проверять заведомо неправильные или гнусные данные, например Можете ли вы представить себе случай, когда для номера телефона требуется что-либо, кроме буквенно-цифровых символов + базовая пунктуация, или он должен быть длиннее, чем длина поля в базе данных? Что касается последнего, то это может смутить или раздражать пользователя, если поле базы данных содержит 128 символов, но вы позволяете пользователю вводить 129 символов, что приводит к некоторой ошибке в пользовательском интерфейсе.

Aaron Newton 19.02.2015 04:17

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

Mike Manard 24.07.2015 01:31

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

lee 13.10.2015 22:15

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

DrewB 12.10.2016 15:14

Если вы хотите, чтобы действительно подтвердил номер телефона ... ТЕЛЕФОН !! Это похоже на нелепые регулярные выражения, которые люди придумали для «проверки адреса электронной почты» ... Если вам действительно важно, что адрес электронной почты действителен, тогда ОТПРАВИТЬ ИМ ПОЧТУ !!

Tom Lord 26.10.2016 12:23

-1, потому что вы можете сделать это поле НЕ обязательным и все равно его нужно будет проверять, чтобы предотвратить случайные орфографические ошибки. Часть ответа «или попробуйте мой мобильный» - это просто чушь, ИМО. Вы передаете формату решение пользователя, следовать ему или нет. Только не делайте этого обязательным, вот и все.

Romeno 16.12.2016 04:37

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

Yarin 09.11.2017 21:46

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

Nabi K.A.Z. 24.02.2019 16:14

Существа вопроса ОП - не вопрос, на который нужно отвечать. Я оставляю этот комментарий только потому, что SO попросил меня, но теперь жалуется на ссылку на мой голос.

Altimus Prime 29.11.2019 06:49

Я писал проще всего (хотя точки мне в нем не понадобились).

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

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

это проверяет тонны чисел, которые технически недействительны. например, «- + () () ()) ())))». Научитесь читать регулярные выражения, чтобы понимать, что вы делаете.

Steven Soroka 28.03.2013 18:47

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

happyhardik 23.08.2013 22:44

это также соответствует пробелу, пустой строке

Wasim A. 16.09.2013 12:13

@HappyHardik. Верно. Простой и мощный, для базовой проверки позволяет пользователю вводить более одной точки, тире, скобки или плюса.

dijipiji 04.02.2014 16:18

Просто использовал, и это неправильно во многих аспектах. Например, номер телефона в Великобритании может начинаться с +44 или в номере телефона может быть (0). Но это не соответствует вашему регулярному выражению. Я бы порекомендовал ответ @Ismael Miguel. Он работает нормально, и я бы порекомендовал вам пересмотреть свой ответ.

Stelios Voskos 29.07.2015 13:44

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

ты решил это?

Sultan Ali 03.03.2021 15:13

Я нашел это кое-что интересным. Я не тестировал, но похоже, что это сработает

<?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.';
}
?>

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

Alastair Irvine 30.09.2013 07:33
bitrepository.com/how-to-validate-a-telephone-number.html looks to be the source.
James Paterson 12.01.2016 18:40

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

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

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

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

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

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

Christopher King 17.01.2014 19:12

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

zfj3ub94rf576hc4eegm 24.04.2020 13:29

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

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.

Обновлено:

Решение 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.info("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();
});


});

Источник.

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

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

В своем руководстве они даже рассказывают, как маскировать ввод номера телефона.

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

((\+[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

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

stormwild 26.02.2014 09:41

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

/^[+#*\(\)\[\]]*([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

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

Вот тот, который хорошо работает в JavaScript. Это строка, потому что это то, чего ожидал виджет Dojo.

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

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

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

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

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

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

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

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

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

Как и в верхнем ответе, удалите все безобразия из номера телефона, чтобы у вас осталась строка числовых символов с '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's 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

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

Я также предлагаю взглянуть на библиотеку 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, но люди также внедрили библиотеки для других языков, которые используют набор данных телефонных номеров Google i18n:

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

Отмечая, что теперь есть порт Go по адресу: github.com/ttacon/libphonenumber

michaelhanson 12.09.2016 21:59

При проверке, является ли это возможным числом, разве вам не нужно указывать код страны? Я использую версию PHP, и если я введу британский номер, например (замените 0 на действительные числа) 07700000000, я получу ошибку Missing or invalid default region.. Но если я укажу код страны, он пройдет.

BugHunterUK 29.11.2016 02:22

К вашему сведению: эта библиотека не поддерживает некоторые страны, phpinterviewquestions.co.in/blog/ionic/…

sijo vijayan 22.07.2017 11:26

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

IMSoP 22.03.2018 19:56

Считайте github.com/nyaruka/phonenumbers «официальным» пакетом Go, рекомендованным Google, а не libphonenumber.

DeeZone 06.05.2019 17:59

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

dimplex 09.07.2020 10:43

/^(?:(?:\(?(?: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

Это было самое полное регулярное выражение, которое я когда-либо видел. Легко обойтись, пока вы не удалите ^ и $, иначе я смогу обойти это, используя [111] [111] [1111] или 111--111--1111 и тому подобное. (извините, удалил мой последний комментарий)

bafromca 08.03.2014 00:10

Не могли бы вы перефразировать? Я не могу понять этого: «Легко обойти, пока вы не удалите ^ и $, иначе я смогу обойти это с помощью [111] [111] [1111]». Означает ли это, что он проверяет «[111] [111] [1111]», когда вы берете ^ и $?

Ismael Miguel 08.03.2014 00:13

Я обошел ваше регулярное выражение, используя [111] [111] [1111] и 111--111--1111, пока я не удалил ^ и $ из регулярного выражения.

bafromca 08.03.2014 00:15

Как я уже спрашивал, какой движок вы используете? 111-111-1111 отлично проверяет (синтаксически второй действителен), в то время как [111] [111] [1111] не проверяет (как и ожидалось)

Ismael Miguel 08.03.2014 00:18
gethifi.com/tools/regex and I meant 111--111--1111 as mentioned above.
bafromca 08.03.2014 00:21

111--111--1111 недействителен: i62.tinypic.com/2rnhr7k.png (отлично) и [111] [111] [1111] также недействителен: i58.tinypic.com/9ru64y.png (как и ожидалось)

Ismael Miguel 08.03.2014 00:25

давайте продолжить обсуждение в чате

bafromca 08.03.2014 01:57

^^^ Это отличный пример того, почему темы комментариев НЕ должны идти в чат. Мне очень интересно, чем закончился этот разговор, и мне нужно знать, достаточно ли прочен этот ReGex для использования в моем приложении. К сожалению, разговора в чате больше нет.

Matt Cashatt 18.07.2014 20:53

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

Ismael Miguel 19.07.2014 22:09

Как мне сделать так, чтобы он мог извлекать номер из строки в любом месте, где может быть номер телефона?

Kousha 17.02.2017 03:29

@Kousha Удалите ^ и $, и он должен работать с множеством ложных срабатываний.

Ismael Miguel 17.02.2017 03:31

@Kousha Это ожидалось. Вы пытаетесь заставить Javascript RegExp работать на PHP с помощью PCRE. Его нужно немного переписать. Что выходит за рамки этого вопроса. Используя regex101.com, вставив туда регулярное выражение и перейдя в «инструменты» -> «генератор кода», вы получите следующее: /(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\/]?){0,})(?:[\-\.\ \\/]?(?:#|ext\.?|extension|x)[\-\.\ \\/]?(\d+))?/i. И этот работает.

Ismael Miguel 17.02.2017 04:18

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

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!';
}

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

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

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

Регулярное выражение:

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

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

function phoneToTel($number) {
    $return = preg_replace('/(\+*\d{1,})*([ |\(])*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4})/', '<a href = "tel:"> () -</a>', $number); // includes international
    return $return;
}

Это регулярное выражение соответствует +1 1234562222222222222222222222.

Varda Elentári 13.10.2015 21:39

почему бы просто не вернуться?

thexande 09.03.2017 00:21

Ложноположительный результат "9999999999999999999999999999999999999"

Ben Wheeler 25.03.2020 19:26

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

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

Краткая шпаргалка

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

Это очень полезно, но я сомневаюсь и ищу выражение {min, max}. Вы можете помочь?

Ataboy Josef 07.01.2015 11:02

Если это одна цифра, о которой мы говорим (и вы можете сопоставить ее в соответствии с этим), посмотрите блок [2-9], который я там поместил. Это означает, что ваш минимум равен 2, а ваш максимум равен 9. Отрегулируйте соответственно.

vapcguy 08.01.2015 00:00

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

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

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

Положительные:
+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

Отрицательный:
926 3 4
8 800 600-ЯБЛОКО

Первоисточник: http://www.regexr.com/38pvb

Это имеет некоторую ограниченную поддержку расширений. Соответствует «616-555-1234 x567», но не «616-555-1234 доб. 567».

Jon Schneider 24.06.2016 00:01

Ложное срабатывание, например, "------- ((((((55555555" или "99999999999999999999999"

mikep 23.11.2017 14:46

Он не проверяет номер макдональдса Нидерландов +31 76596 4192 (я просто проверял случайные числа)

BIOHAZARD 09.12.2018 18:28

/\b(\d{3}[^\d]{0,2}\d{3}[^\d]{0,2}\d{4})\b/

Я обнаружил, что это работает довольно хорошо:

^\(*\+*[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

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

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

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

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

Примечание Он принимает в качестве входных данных номер мобильного телефона в США в любом формате и дополнительно принимает второй параметр - установите значение 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;
        }
    }

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

if (!phoneNumber.matches("^[6-9]\d{9}$")) {
  return false;
} else {
  return true;
}

Почему бы просто не вернуть вывод matches?

nice_dev 25.01.2019 19:30

Поскольку в этом посте нет языкового тега, я дам решение 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

Вот что я использую

function isValidTel ($tel) {
    preg_match('/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im', $tel, $matches);
    return !! $matches;
}

Проверьте это в этом тестере регулярных выражений https://www.phpliveregex.com/p/uld

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

mickmackusa 31.07.2020 23:30

поскольку есть так много возможностей написать номер телефона, можно просто проверить, достаточно ли в нем цифр, как бы они ни были разделены. Я обнаружил, что для меня работают от 9 до 14 цифр:

^\D*(\d\D*){9,14}$

истинный:

  • 123456789
  • 1234567890123
  • +123 (456) 78,90-98,76

ложный:

  • 123
  • (1234) 1234
  • 9007199254740991
  • 123 не буду делать то, что ты мне говоришь
  • +123 (456) 78.90-98.76 # 543 доб 210> 2> 5> 3
  • (123) 456-7890 утром (987) 54-3210 после 18:00 и спросить Ширли

если вы используете хочу для поддержки этих двух последних примеров - просто удалите верхний предел:

(\d\D*){9,}

(^$ не нужен, если нет верхнего предела)

Java генерирует REGEX для действительных номеров телефонов

Другая альтернатива - позволить Java генерировать REGEX, который отображает все варианты телефонных номеров, считываемых из списка. Это означает, что список с именем validPhoneNumbersFormat, показанный ниже в контексте кода, определяет, какой формат номера телефона является допустимым.

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

Фрагмент кода, который генерирует REGEX:

Set<String> regexSet = uniqueValidPhoneNumbersFormats.stream()
        .map(s -> s.replaceAll("\+", "\\+"))
        .map(s -> s.replaceAll("\d", "\\d"))
        .map(s -> s.replaceAll("\.", "\\."))
        .map(s -> s.replaceAll("([\(\)])", "\\"))
        .collect(Collectors.toSet());

String regex = String.join("|", regexSet);

Фрагмент кода в контексте:

public class TestBench {

    public static void main(String[] args) {
        List<String> validPhoneNumbersFormat = Arrays.asList(
                "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",
                "+12345678901",
                "(234) 567-8901 ext. 123",
                "+1 234-567-8901 ext. 123",
                "1 (234) 567-8901 ext. 123",
                "00 1 234-567-8901 ext. 123",
                "+210-998-234-01234",
                "210-998-234-01234",
                "+21099823401234",
                "+210-(998)-(234)-(01234)",
                "(+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"
        );

        Set<String> uniqueValidPhoneNumbersFormats = new LinkedHashSet<>(validPhoneNumbersFormat);

        List<String> invalidPhoneNumbers = Arrays.asList(
                "+210-99A-234-01234",       // FAIL
                "+210-999-234-0\"\"234",    // FAIL
                "+210-999-234-02;4",        // FAIL
                "-210+998-234-01234",       // FAIL
                "+210-998)-(234-(01234"     // FAIL
        );
        List<String> invalidAndValidPhoneNumbers = new ArrayList<>();
        invalidAndValidPhoneNumbers.addAll(invalidPhoneNumbers);
        invalidAndValidPhoneNumbers.addAll(uniqueValidPhoneNumbersFormats);

        Set<String> regexSet = uniqueValidPhoneNumbersFormats.stream()
                .map(s -> s.replaceAll("\+", "\\+"))
                .map(s -> s.replaceAll("\d", "\\d"))
                .map(s -> s.replaceAll("\.", "\\."))
                .map(s -> s.replaceAll("([\(\)])", "\\"))
                .collect(Collectors.toSet());

        String regex = String.join("|", regexSet);

        List<String> result = new ArrayList<>();
        Pattern pattern = Pattern.compile(regex);
        for (String phoneNumber : invalidAndValidPhoneNumbers) {
            Matcher matcher = pattern.matcher(phoneNumber);
            if (matcher.matches()) {
                result.add(matcher.group());
            }
        }

        // Output:
        if (uniqueValidPhoneNumbersFormats.size() == result.size()) {
            System.out.println("All valid numbers was matched!\n");
        }    
        result.forEach(System.out::println); 
    }

}

Выход:

All valid numbers was matched!

1-234-567-8901
1-234-567-8901 x1234
1-234-567-8901 ext1234
...
...
...

Хотя это не регулярное выражение, вы можете использовать функцию validate_phone() из библиотеки Python DataPrep для проверки телефонных номеров в США. Установите его с помощью pip install dataprep.

>>> from dataprep.clean import validate_phone
>>> df = pd.DataFrame({'phone': ['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, '12345678', '123-456-78987']})
>>> validate_phone(df['phone'])
0     True
1     True
2     True
3     True
4     True
5     True
6     True
7    False
8    False
Name: phone, dtype: bool

Другие вопросы по теме