Я пытаюсь собрать комплексное регулярное выражение для проверки телефонных номеров. В идеале он должен работать с международными форматами, но он должен работать с американскими форматами, включая следующие:
1-234-567-89011-234-567-8901 x12341-234-567-8901 ext12341 (234) 567-89011.234.567.89011/234/567/890112345678901Я отвечу своей текущей попыткой, но я надеюсь, что у кого-то есть что-то получше и / или более элегантно.





Вот моя лучшая попытка. Он поддерживает форматы, указанные выше, но я уверен, что мне не хватает других возможных форматов.
^\d?(?:(?:[\+]?(?:[\d]{1,3}(?:[ ]+|[\-.])))?[(]?(?:[\d]{3})[\-/)]?(?:[ ]+)?)?(?:[a-zA-Z2-9][a-zA-Z0-9 \-.]{6,})(?:(?:[ ]+|[xX]|(i:ext[\.]?)){1,2}(?:[\d]{1,5}))?$
Работал как шарм! Спасибо, что поделился
Вы видели RegExLib?
Ввод номера телефона в США вернул целый список возможностей.
Похоже, это отличный способ интегрировать малоизвестные ошибки в ваш код.
Следует избегать ответов, содержащих только ссылки, потому что они могут сломаться в будущем и сделать сообщение бесполезным. Статические решения всегда необходимы для поддержания ценности ответа. Если вы хотите порекомендовать гиперссылку, добавьте ее в качестве комментария под вопросом.
Оказывается, для этого есть что-то вроде спецификации, по крайней мере для Северной Америки, которая называется 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}) $
У меня это хорошо сработало. Мне нужно было обновить часть расширения, добавив косую черту перед #, иначе он говорит, что оттуда есть комментарий
А как насчет добавления "(" и ")" к этому списку разделителей?
Вот версия, которая соответствует только 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})/
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}).
@StevenSoroka Последние два года рядом со мной на столе лежит книга Джеффри Фридла, поскольку регулярные выражения - основная часть моей работы. Чтобы по-настоящему понять регулярные выражения, нужно время. Иногда читатели этого сайта просто ищут существующее решение, а не пишут собственное, особенно в доменах с большим количеством угловых случаев, таких как представление телефонных номеров.
@ fatcat1111 Я понимаю это, но большинство ответов здесь относятся к разовым регулярным выражениям типа «я тоже», которые, вероятно, не подходят ни для одного из ваших угловых случаев. Затем они попадают на все веб-сайты, которые я пытаюсь использовать, и я не могу ввести свой почтовый индекс, номер телефона или адрес электронной почты, потому что кто-то использовал недолговечное регулярное выражение (например: + - допустимый символ в адресах электронной почты. ). Лучшие ответы на этой странице указывают пользователям на библиотеки, а не на нарисованные на салфетке регулярные выражения.
Будьте осторожны и проверяйте наличие неразрывных пробелов при копировании этих выражений.
Интересно, изменилось ли что-то с тех пор, как вы впервые разместили это? Он не соответствует хотя бы одному допустимому коду города: 410 (Мэриленд). 410 - это упомянул в статье Википедии, на которую вы ссылаетесь, но 410 находился в обслуживании с 1991 года.
Похоже, это работает с каждым сценарием, который я использовал. Я даже ввел неверный код области, например, код области, который начинается с 1, недействителен, и он его поймал. AAA +++ Perfection для телефонных номеров в США ..
Пример того, где это регулярное выражение не работает: 866-411-1234 (потому что он не разрешает обмен 411 в соответствии с правилами NANPA, но это нормально для номеров 8xx). regex101.com/r/3DSYIr/1
Лучший вариант ... просто удалите все нецифровые символы при вводе (кроме знаков 'x' и ведущих '+'), заботясь о британской тенденции писать числа в нестандартной форме +44 (0) ..., когда их просят использовать международный префикс (в этом конкретном случае вы должны полностью отказаться от (0)).
Тогда вы получите такие значения, как:
12345678901
12345678901x1234
345678901x1234
12344678901
12345678901
12345678901
12345678901
+4112345678
+441234567890
Затем, когда вы отображаете, переформатируйте, как вам нравится. например
1 (234) 567-8901
1 (234) 567-8901 x1234
Код форматирования будет пустой тратой времени, если числам разрешено поступать из-за пределов США.
@Earwicker - согласился, что форматирование (при работе с международными #) должно быть достаточно умным, чтобы обрабатывать различные форматы ... например. (0123) 456 7890 или +1 234 567-89-01. В зависимости от того, насколько сложно вы хотите получить, это должно быть что-то, что можно вычислить на основе количества цифр и того, каковы первые несколько цифр.
Это хорошо и все такое, но не проверяет, что было введено на самом деле телефонным номером. Например, что, если пользователь не вводит необходимые 10 цифр? Это должно сочетаться с хорошей проверкой регулярного выражения.
string.replace ("[^ \ d +! x]", "")
jcmcbeth, почему !x часть? Кажется, этого достаточно: [^\d+]rubular.com/r/aj32fRSSGK
@danilo -! x предназначен для предотвращения удаления любого символа «x», чтобы можно было отделить расширения.
Учитывая, что вопрос был о валидации - это действительно плохой ответ.
@PlexQ Я не согласен. Исходная проблема заключается в попытке обработать проверку номера телефона, потому что он пытался обработать все возможные параметры форматирования. Вместо того, чтобы пытаться решить все это, возьмите входные данные и «предварительно удалите» из них весь форматирующий мусор, пока у вас не будет только «число». Это решает 2 проблемы: теперь легко проверить результат, и теперь вы можете убедиться, что значения, отображаемые для отображения, могут быть отформатированы единообразно. Хорошее прочтение первого комментария к этому ответу о «Перчатках для усложнителя» ... иногда ответ на проблему состоит в том, чтобы подойти к ней по-другому.
Для других, кто может использовать вышеупомянутый [^\d+!x] - восклицательный знак не нужен. Просто используйте [^\d+x]. См. stackoverflow.com/questions/10340336/….
@Raymond, вы можете использовать $justDigitsOrPlusOrX = preg_replace("/[^\d+x]/", "", $phoneNum);, чтобы удалить все символы, которые вам не нужны ... затем проверьте оставшиеся (при необходимости)
Это прекрасно работает, за исключением чисел вроде 1-800-CALL-NOW?
@Swan и я полагаю, что в этих сценариях, если вы действительно этого хотите, вы могли бы включить умный перевод, который преобразовывал бы буквы в соответствующие числа ... но я думаю, что это очень особенный угловой случай по сравнению с тем, что нужно большинству людей. ;-)
Улучшение Regex выше: /[^\d+x]|x(?=[^x]*x)/gi Предотвращает множественные x (использует последний x в строке)
Это хорошо, но не отвечает на поставленный вопрос, в котором явно запрашивается решение RegEx.
@nashwan, вы читали статью, указанную в первом комментарии, добавленном Николасом Трандемом. Плакат с исходным вопросом? Иногда (как вы можете видеть, как проголосовало сообщество), даже если есть решение использовать регулярное выражение из 261 символа, которое обрабатывает множество сценариев ... попытка атаковать проблему другим способом - это на самом деле ответ, который вы хотите. Обратите внимание, что ответ Дэйва Кирби также предлагает не использовать строгое регулярное выражение ... также набирает (ATM 79 голосов)
@Swanand Это мило, когда люди объясняют вещи в буквенных обозначениях, которые есть на большинстве телефонных клавиатур, но в стандартах это не поощряется. tools.ietf.org/html/rfc3966#section-5.1.2
Вы не можете просто разрешить что-либо, а затем удалить то, что вам не нужно, если планируете форматировать позже. Вам нужно что-то, что вы можете отформатировать позже.
Я должен пояснить, что я буду «хранить» чистое значение и только «украшать» его по мере необходимости для отображения позже.
Вам нужно быть осторожным, когда вам будет представлен номер, начинающийся с +44 (0). Это очень распространенный формат в Великобритании, и вы, вероятно, захотите сопоставить его с +44 (т.е. удалить (0)).
Да, проверка или форматирование телефонных номеров - не лучшая идея. Ниже приведены действительные номера телефонов в Германии: +49 (0) 89 12345, +49 (0) 6221 1234. Если вы находитесь в Германии, набирайте их как 089 12345 или 06221 1234, но, например, В Швейцарии это будет 0049 89 12345 или 0049 6221 1234. Это похоже на случай Великобритании, но наши коды городов не имеют фиксированной длины. Если у вас нет списка, вы не сможете правильно отформатировать числа.
Как, черт возьми, этот ответ получил столько голосов? Это ничего не подтверждать. Что еще хуже, все остальные вопросы о проверке номера телефона ссылаются на этот ...
@ jlars62 он может не проверять номер телефона, но он предлагает альтернативное решение, которое более надежно, чем попытки угадать, действителен ли данный номер телефона, учитывая, что идея действительного значительно различается в разных странах. ИМО, это хорошее решение, хотя я согласен, что оно не подтверждает, что оно все еще решает проблему.
@configurator Ну, телефонные коды страны имеют свойство префикса, поэтому ваш пример (4 (420) 778-457800), если 4 - это код страны, а 420 - код области / города) не может быть реальным числом, однако вы указали, что знак "+" важен для обозначения того, являются ли первые цифры кодом страны. Возможно, лучшим примером будет
Это работает, но добавляет сложности в логику.
Не использует регулярные выражения. +1
См. Также: technet.microsoft.com/en-us/library/cc728034(v=ws.10).aspx При использовании TAPI для набора номера в окнах это может помочь.
Я создал публичная сущность, предоставляющий функцию ES6, основанную на регулярном выражении @AlbertBori. Отзывы приветствуются.
Номера Великобритании (+44) должны содержать 10 цифр после 0 / + 44. например 01234 567 890
@mwfearnley Не все есть с 9 и 7 (также бесплатные с 9 и 7) en.wikipedia.org/wiki/Telephone_numbers_in_the_United_Kingdo м и в живой памяти длина изменилась
Стою исправлюсь .. Я достаточно взрослый, чтобы помнить смену - жил в 0234 году :)
Я размышляю: «из-за британской тенденции писать числа в нестандартной форме +44 (0)» Если это склонность многих людей, разве это не стандарт? (и чертовски раздражает, даже если я делаю это сам).
как это могло быть подтверждено как лучший ответ честно
Неприемлемо, что, если вы не контролируете ввод? это не решает вопрос.
Это отличный ответ. Это показывает, что вы должны преобразовать в целое число, а затем проверить который (предположительно, используя простой алгоритм). Эта часть подразумевается или, по крайней мере, кажется мне очевидной. Проверять номер телефона с помощью регулярного выражения на лету - это безумие. Кроме того ... что нужно проверить в первую очередь? Что это настоящий номер телефона? Почему? Если пользователь предоставляет неверный номер телефона, это их проблема.
это вообще не отвечает на вопрос. о единственном, что дает этот ответ, - это нормализовать ваш ввод. спрашивали не об этом. почему это принятый ответ?
Я работаю в компании по исследованию рынка, и нам приходится фильтровать эти типы входных данных все время. Вы слишком усложняете это. Просто удалите не буквенно-цифровые символы и посмотрите, есть ли расширение.
Для дальнейшего анализа вы можете подписаться на одного из многих провайдеров, который предоставит вам доступ к базе данных действительных номеров, а также сообщит вам, стационарные они или мобильные, отключены и т. д. Это стоит денег.
Проверка? 123% $) *% () $ * () # 456 * () * $ # (* (# $ @ 8908 будет соответствовать вашему предлагаемому решению.
@PlexQ 555-123-1234, 07777777777, 90210, 01.01.1901 - пользователи изобретательны в том, чтобы забивать мусор посредством валидации. Лучше не ставить галочку перед теми, у кого действительно есть какие-то странные данные, используя чрезмерно ограничительную проверку и сообщая им, что они неправы.
Если это вообще возможно, я бы рекомендовал иметь четыре отдельных поля - код города, 3-значный префикс, 4-значная часть, расширение - чтобы пользователь мог вводить каждую часть адреса отдельно, и вы могли проверить каждую часть индивидуально. Таким образом, вы можете не только упростить проверку, но и сохранить свои номера телефонов в базе данных в более согласованном формате.
Однако, если вы решите пойти по этому маршруту, имейте в виду, что это не сработает за пределами США. Невозможно ввести расширение страны и, например, В Германии есть коды городов с переменной длиной (от 2 до 4 цифр, плюс начальный ноль, если вы звоните из Германии, который не учитывается, если перед ним указан код страны).
Вам будет сложно работать с международными номерами с помощью одного / простого регулярного выражения, см. эта почта о трудностях международных (и даже североамериканских) телефонных номеров.
Вам нужно проанализировать первые несколько цифр, чтобы определить код страны, а затем действовать по-разному в зависимости от страны.
Помимо этого - список, который вы предоставили, не включает другой распространенный в США формат - исключая начальную цифру 1. Большинство сотовых телефонов в США не требуют этого, и это начнет сбивать с толку молодое поколение, если они не наберут номер на международном уровне.
Вы правильно определили, что это сложная проблема ...
-Адам
Не предложенное решение. ВОЗМОЖНО. То, что это сложно или сложно, не означает, что вам нужно просто вскинуть руки вверх.
Я считаю, что модули Perl Номер :: Телефон :: США и Regexp :: Common (особенно источник Regexp :: Common :: URI :: RFC2806) могут помочь.
Вопрос, вероятно, следует задать более подробно, чтобы объяснить цель проверки чисел. Например, 911 - допустимый номер в США, но 911x не для любого значения x. Это необходимо для того, чтобы телефонная компания могла рассчитать, когда вы закончите набор номера. Есть несколько вариантов этого вопроса. Но ваше регулярное выражение не проверяет часть кода области, так что это не вызывает беспокойства.
Как и при проверке адресов электронной почты, даже если у вас есть действительный результат, вы не можете узнать, назначен ли он кому-то, пока не попробуете.
Если вы пытаетесь проверить вводимые пользователем данные, почему бы не нормализовать результат и не покончить с этим? Если пользователь вводит число, которое вы не можете распознать как действительное, либо сохраните его как введенное, либо удалите недопустимые символы. Модуль Номер :: Телефон :: Нормализовать Perl может стать источником вдохновения.
Я собираюсь рискнуть и сказать, что использование службы 911 в качестве номера телефона, вероятно, является плохой идеей почти для всех приложений этого регулярного выражения. Впрочем, неплохой улов.
Хотя ответ на удаление всех пробелов прост, на самом деле он не решает поставленную проблему, а именно найти регулярное выражение. Возьмем, к примеру, мой тестовый скрипт, который загружает веб-страницу и извлекает все номера телефонов с помощью регулярного выражения. Поскольку вам в любом случае понадобится регулярное выражение, вы также можете заставить регулярное выражение делать всю работу. Я придумал это:
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 Добавление (^|[^\d\n]) (с включенным многострочным флагом) позволяет избежать общей проблемы, гарантируя, что ей не предшествует что-то числовое.
Обратите внимание, что это ориентировано на Северную Америку - в нем отсутствует "44 7911 123456".
Я склонен согласиться с тем, что убирать нецифровые числа и просто принимать то, что там лучше. Может быть, чтобы убедиться, что присутствует хотя бы пара цифр, хотя это запрещает что-то вроде буквенного телефонного номера, например, «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 x12312 1234 123 1 x111112 12 12 12 1212 1 1234 123456 x12345+12 1234 1234+12 12 12 1234+12 1234 5678+12 12345678Это может быть предвзятым, поскольку мой опыт ограничен Северной Америкой, Европой и небольшой частью Азии.
Я пытался реализовать вышеизложенное в моем сценарии проверки javascript, но продолжаю получать ошибку invalid quantifier. Есть идеи о том, что я делаю неправильно?
Я бы добавил тривиальный случай, когда телефон указан без символов, но, возможно, с пробелами и кодом страны, в Европе это типично для местных и мобильных номеров: 676412342, 676 46 32 12, 676463212
Я боролся с той же проблемой, пытаясь сделать свое приложение перспективным, но эти ребята заставили меня двигаться в правильном направлении. Я на самом деле не проверяю сам номер, чтобы узнать, работает он или нет, я просто пытаюсь убедиться, что была введена серия чисел, которые могут иметь или не иметь расширение.
В худшем случае, если бы пользователю приходилось извлекать неформатированный номер из XML-файла, он все равно просто вводил бы цифры в цифровую клавиатуру телефона 012345678x5, и это не было реальной причиной для того, чтобы сохранять его красивым. Такой тип RegEx выйдет для меня примерно так:
\d+ ?\w{0,9} ?\d+
01234467 extension 12345601234567x12345601234567890Замените символы форматирования, затем проверьте оставшиеся на соответствие телефону. В 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: Да, но даже если это действительный номер, это не означает, что это существующий номер, и даже если он существует, это не означает, что это номер пользователя. Если это так важно, вам нужно настроить автоматическую систему, которая будет звонить им, чтобы проверить ... Если ваш бюджет так велик :)
@Benjol да, это правда - на мое личное мнение, вероятно, влияет тот факт, что на одном из моих ноутбуков есть липкая клавиша "5" :-)
Я согласен с точки зрения удобства использования, но разрешение произвольного ввода может подвергнуть ваш веб-сайт атакам с использованием межсайтовых сценариев (XSS). Злоумышленник может внедрить JavaScript в строку вашего номера телефона произвольной формы.
Иногда пользователям необходимо указать действующий номер телефона. Если вы заявите, что это часть ToS - дать один, они не могут дать поддельный без нарушения. Если вы хотя бы убедитесь с точки зрения проверки, что то, что они дали, синтаксически правильно, это избавит вас от многих головных болей.
Обычно я склоняюсь к такому образу мышления с пользовательским опытом. Действительный номер телефона в США состоит из 10 цифр: ^(.*\d.*){10,}$. Это позволяет вводить его любым удобным для пользователя способом. Затем на серверной части удалите недопустимые символы.
@Pointy Но проверка регулярного выражения вам не поможет. Единственный способ проверить правильность номера телефона - это отправить ему сообщение (в случае мобильного телефона) И убедиться, что пользователь подтверждает, используя какой-то проверочный код. Это то, что вы делаете, когда важна правильность номера. Все остальное просто для удобства пользователя, чтобы защитить от некоторых (но не всех) опечаток и ничего не проверяет.
@AlexB, конечно, я это понимаю, но если вы можете помочь мне отловить ошибку отсутствия цифры, это избавит меня от (небольших) неудобств, связанных с получением ошибки на стороне сервера, ее интерпретацией, повторным поиском поля и т. д.
Есть миллион случаев использования, когда это решение в виде простого текста является ответом. Но есть миллион случаев, когда это может вызвать множество проблем. Посмотрите, как вы используете номер телефона и почему вы его просите. Затем вы можете решить, какая методология подходит вам. Если вы не знаете, почему вы спрашиваете или как вы его используете, вам, вероятно, вообще не следует спрашивать номер телефона.
Верно, но тогда вы могли бы просто сделать что-нибудь вроде «когда не пусто, проверить». Что-то вроде if (!empty($telephone) && !validation_function($telephone)) { //throw_error }, тогда вы можете НЕ вводить свой номер.
Здорово. Мой номер телефона - 1 'ИЛИ 1 = 1 - ЗАПРЕЩЕНО. См. xkcd.com/327 и owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005).
Ответ содержит глубочайшую мудрость.
В моем случае мне нужно было подтвердить номер телефона, поскольку это был самый простой способ определить, кто рассылал спам в форме. Это спамеры использовали неверные номера телефонов. Кроме того, это была форма запроса, поэтому мы планировали вызвать всем, кто ее заполнил, и номер телефона был обязательным полем.
@EvanDonovan Тогда вы пропустите мою запись, потому что я буду использовать фиктивный телефон, если только не хочу, чтобы вы мне перезвонили, что очень маловероятно
@Mark: Меня это не слишком беспокоит. Очевидно, я не могу захватить все с помощью регулярного выражения. В этом случае спамеры не вводили никаких действительных данных в форму, тогда как я предполагаю, что если бы вы заполняли форму, вы, по крайней мере, вводили бы действительное электронное письмо.
Этот ответ не отвечает на вопрос - скорее, он просто способствует непереносимости форм, то есть уже присуще всем нам.
@AaronNewton: выполнение проверки на уровне формы или использование регулярных выражений в любом случае небезопасно, есть лучшие способы предотвратить внедрение sql.
@CommuSoft, это правда. Однако лучшим заявлением может быть не полагайтесь исключительно на регулярное выражение для предотвращения SQL-инъекции. Я бы все равно сказал, что имеет смысл проверять заведомо неправильные или гнусные данные, например Можете ли вы представить себе случай, когда для номера телефона требуется что-либо, кроме буквенно-цифровых символов + базовая пунктуация, или он должен быть длиннее, чем длина поля в базе данных? Что касается последнего, то это может смутить или раздражать пользователя, если поле базы данных содержит 128 символов, но вы позволяете пользователю вводить 129 символов, что приводит к некоторой ошибке в пользовательском интерфейсе.
Этот ответ непочтителен и никоим образом не имеет отношения к вопросу. OP попросил помощи в проверке формата ввода от пользователя; не для вашего личного мнения о том, должен ли он. Возможный вариант использования: веб-сайт предназначен для внутреннего использования компанией - это не означает использование интрасети, скорее, у этой компании есть сотрудники, которые работают «в полевых условиях» и общаются с сотрудниками офиса через этот веб-сайт. Им нужно, чтобы человек ввел действительный номер телефона, по которому с ними можно связаться, как часть их должностных требований, и они хотят избежать простых ошибок, которые могут вызвать головную боль.
. * - это регулярное выражение, которое будет проверять ноль или более символов любого типа как действительные, что не соответствует цели проверки номера телефона.
Конечно, это не учитывает формы, для которых требуется номер телефона. В настоящее время я создаю приложение для отслеживания лицензионной информации в нашей организации. Требуются номера телефонов поставщиков, поэтому я определенно хотел бы их подтвердить.
Если вы хотите, чтобы действительно подтвердил номер телефона ... ТЕЛЕФОН !! Это похоже на нелепые регулярные выражения, которые люди придумали для «проверки адреса электронной почты» ... Если вам действительно важно, что адрес электронной почты действителен, тогда ОТПРАВИТЬ ИМ ПОЧТУ !!
-1, потому что вы можете сделать это поле НЕ обязательным и все равно его нужно будет проверять, чтобы предотвратить случайные орфографические ошибки. Часть ответа «или попробуйте мой мобильный» - это просто чушь, ИМО. Вы передаете формату решение пользователя, следовать ему или нет. Только не делайте этого обязательным, вот и все.
Вопрос был не в проверке ввода данных пользователем. Это может быть проверка списка агрегированных телефонных номеров из нескольких систем, собранных в разное время с помощью разных форм. Грязные данные поступают из самых разных источников.
Я думаю, ты ошибся. Это несложный способ получить от пользователя правильный номер, потому что, как вы упомянули, пользователь может в конечном итоге сбежать и ввести номер другого человека. Это проверка номера для классификации информации, чтобы в будущем у нас была чистая информация без какой-либо дополнительной информации и лишних символов от пользователя для возможного использования в будущем.
Существа вопроса ОП - не вопрос, на который нужно отвечать. Я оставляю этот комментарий только потому, что SO попросил меня, но теперь жалуется на ссылку на мой голос.
Я писал проще всего (хотя точки мне в нем не понадобились).
^([0-9\(\)/\+ \-]*)$
Как упоминалось ниже, он проверяет только символы, а не их структуру / порядок.
это проверяет тонны чисел, которые технически недействительны. например, «- + () () ()) ())))». Научитесь читать регулярные выражения, чтобы понимать, что вы делаете.
@StevenSoroka технически может допускать множество недействительных случаев, но когда мы думаем о том, чтобы просто помочь пользователю избежать распространенных ошибок с помощью простейшего возможного решения, это выход :)
это также соответствует пробелу, пустой строке
@HappyHardik. Верно. Простой и мощный, для базовой проверки позволяет пользователю вводить более одной точки, тире, скобки или плюса.
Просто использовал, и это неправильно во многих аспектах. Например, номер телефона в Великобритании может начинаться с +44 или в номере телефона может быть (0). Но это не соответствует вашему регулярному выражению. Я бы порекомендовал ответ @Ismael Miguel. Он работает нормально, и я бы порекомендовал вам пересмотреть свой ответ.
Обратите внимание, что удаление символов () не работает для стандартного стиля написания британских номеров: +44 (0) 1234 567890, что означает набор международного номера:
.
+441234567890
или в Великобритании наберите 01234567890
См. Также Международная запись номеров Великобритании
ты решил это?
Я нашел это кое-что интересным. Я не тестировал, но похоже, что это сработает
<?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.';
}
?>
Ваше сообщение, похоже, указывает на то, что вы не писали этот код. Не могли бы вы процитировать источник?
pattern = "^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$"
validateat = "onsubmit"
Должен заканчиваться цифрой, может начинаться с (или + или цифры, и может содержать + - (или)
Мое чутье подкрепляется количеством ответов на эту тему - что существует практически бесконечное количество решений этой проблемы, ни одно из которых не будет элегантным.
Честно говоря, я бы порекомендовал вам не пытаться проверять номера телефонов. Даже если бы вы могли написать большой и сложный валидатор, который разрешал бы все различные допустимые форматы, он в конечном итоге разрешил бы практически все, даже отдаленно напоминающее номер телефона.
На мой взгляд, наиболее элегантным решением является проверка минимальной длины, не более того.
Попробовав несколько из них и просмотрев существующие данные и отзывы пользователей, я склонен согласиться ...
Однако иногда вам нужно выполнить проверку. Если я отправляю коды подтверждения, я не могу просто отправить код в любой случайный мусор, который спаммер ввел в это поле. Я хочу убедиться, что это номер телефона наверное, прежде чем тратить ресурсы на его отправку.
Для всех, кто хочет сделать что-то подобное с ирландскими номерами мобильных телефонов, вот простой способ сделать это:
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?
Моя попытка неограниченного регулярного выражения:
/^[+#*\(\)\[\]]*([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).
Используя один из ваших более сложных примеров, 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
При проверке, является ли это возможным числом, разве вам не нужно указывать код страны? Я использую версию PHP, и если я введу британский номер, например (замените 0 на действительные числа) 07700000000, я получу ошибку Missing or invalid default region.. Но если я укажу код страны, он пройдет.
К вашему сведению: эта библиотека не поддерживает некоторые страны, phpinterviewquestions.co.in/blog/ionic/…
@BugHunterUK (и любой, кто сталкивается с этим вопросом и задается вопросом о том же) при синтаксическом анализе числа, вы можете указать ожидаемый регион, и библиотека будет искать немеждународные номера в этом регионе. Если вы не укажете, он отклонит все, что не соответствует допустимому международному формату.
Считайте github.com/nyaruka/phonenumbers «официальным» пакетом Go, рекомендованным Google, а не libphonenumber.
Я могу подтвердить то, что говорит @BugHunterUK. Потребовалось время, чтобы добраться туда, но результат оказался именно таким, как и ожидалось - местные номера принимаются в любом формате плюс все полностью определенные международные форматы.
/^(?:(?:\(?(?: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 экономится:
Можете протестировать на https://www.regexpal.com/?fam=99127
Это было самое полное регулярное выражение, которое я когда-либо видел. Легко обойтись, пока вы не удалите ^ и $, иначе я смогу обойти это, используя [111] [111] [1111] или 111--111--1111 и тому подобное. (извините, удалил мой последний комментарий)
Не могли бы вы перефразировать? Я не могу понять этого: «Легко обойти, пока вы не удалите ^ и $, иначе я смогу обойти это с помощью [111] [111] [1111]». Означает ли это, что он проверяет «[111] [111] [1111]», когда вы берете ^ и $?
Я обошел ваше регулярное выражение, используя [111] [111] [1111] и 111--111--1111, пока я не удалил ^ и $ из регулярного выражения.
Как я уже спрашивал, какой движок вы используете? 111-111-1111 отлично проверяет (синтаксически второй действителен), в то время как [111] [111] [1111] не проверяет (как и ожидалось)
111--111--1111 недействителен: i62.tinypic.com/2rnhr7k.png (отлично) и [111] [111] [1111] также недействителен: i58.tinypic.com/9ru64y.png (как и ожидалось)
давайте продолжить обсуждение в чате
^^^ Это отличный пример того, почему темы комментариев НЕ должны идти в чат. Мне очень интересно, чем закончился этот разговор, и мне нужно знать, достаточно ли прочен этот ReGex для использования в моем приложении. К сожалению, разговора в чате больше нет.
Если честно, я не ходил в чат. После того, как я несколько раз просил объяснений, я остался без информации. Вы всегда можете попробовать сами со всеми видами чисел, которые найдете в Интернете, в разных форматах. Одна вещь, которую я пробовал с этим, - использовать несколько телефонных номеров, но он не работает так хорошо, если вокруг них есть пробелы. И мне нужно найти решение, чтобы подсчитать количество цифр и обеспечить соблюдение определенной суммы.
Как мне сделать так, чтобы он мог извлекать номер из строки в любом месте, где может быть номер телефона?
@Kousha Удалите ^ и $, и он должен работать с множеством ложных срабатываний.
@Kousha Это ожидалось. Вы пытаетесь заставить Javascript RegExp работать на PHP с помощью PCRE. Его нужно немного переписать. Что выходит за рамки этого вопроса. Используя regex101.com, вставив туда регулярное выражение и перейдя в «инструменты» -> «генератор кода», вы получите следующее: /(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\/]?){0,})(?:[\-\.\ \\/]?(?:#|ext\.?|extension|x)[\-\.\ \\/]?(\d+))?/i. И этот работает.
Рабочий пример для Турции, просто измените
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.
почему бы просто не вернуться?
Ложноположительный результат "9999999999999999999999999999999999999"
Я ответил на этот вопрос по другому вопросу 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}. Вы можете помочь?
Если это одна цифра, о которой мы говорим (и вы можете сопоставить ее в соответствии с этим), посмотрите блок [2-9], который я там поместил. Это означает, что ваш минимум равен 2, а ваш максимум равен 9. Отрегулируйте соответственно.
Вот замечательный паттерн, который наиболее точно соответствует проверке, которой мне нужно было добиться. Я не являюсь первоначальным автором, но я думаю, что этим стоит поделиться, поскольку я нашел эту проблему очень сложной и без краткого или широко полезного ответа.
Следующее регулярное выражение будет улавливать широко используемые комбинации цифр и символов в различных форматах глобальных телефонных номеров:
/^\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».
Ложное срабатывание, например, "------- ((((((55555555" или "99999999999999999999999"
Он не проверяет номер макдональдса Нидерландов +31 76596 4192 (я просто проверял случайные числа)
/\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?
Поскольку в этом посте нет языкового тега, я дам решение 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
В вашем необъяснимом ответе я замечаю, что ваш шаблон без необходимости использует классы символов в некоторых точках, без необходимости экранирует в других точках и использует модификатор шаблона без учета регистра в шаблоне без букв. Я никому не рекомендую этот ответ - он рекомендует бессмысленный синтаксис.
поскольку есть так много возможностей написать номер телефона, можно просто проверить, достаточно ли в нем цифр, как бы они ни были разделены. Я обнаружил, что для меня работают от 9 до 14 цифр:
^\D*(\d\D*){9,14}$
истинный:
ложный:
если вы используете хочу для поддержки этих двух последних примеров - просто удалите верхний предел:
(\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
Этот ответ был добавлен в Часто задаваемые вопросы о регулярных выражениях при переполнении стека в разделе «Общие задачи проверки».