Як перевірити номери телефонів за допомогою регулярного вираження


920

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

  • 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

Я відповім моєю сьогоднішньою спробою, але сподіваюся, що у когось є щось краще та / або більш елегантне.


3
До речі, вам слід вказати, якою мовою ви користуєтесь. Не всі двигуни регулярного вираження мають однаковий синтаксис.
AndrewJFord

9
Здається, ви випустили варіант +1 замість лише 1, хоча відповідь охоплює цей випадок.
Ерік

153
Чи не потрібні всі номери телефонів у США, 555крім них 911?
Ендрю Грімм

41
Навпаки, префікс 555 зарезервований для підроблених номерів телефонів. Ці номери гарантовано не підключаються до фактичного номера телефону, тому їх часто використовують у телебаченні та фільмах, щоб глядач не намагався зателефонувати на номер і в кінцевому підсумку переслідував когось поганого невинного.
rushinge

49
@rushinge Хоча це було правдою десятиліття тому, це більше не відповідає дійсності . Префікс 555 все ще є спеціальним, але лише невеликий діапазон чисел гарантовано закінчується без з'єднання 555-0100 до 555-0199. Але я майже впевнений, що Ендрю все одно жартував.
Адам Девіс

Відповіді:


515

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

Потім у вас з’являються такі значення, як:

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

Потім, показуючи, переформатуйте вміст серця. напр

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

35
Код форматування буде марною витратою часу, якщо номери дозволять надходити за межі США.
Даніель Ервікер

26
Це добре і все, але це не підтверджує те, що було введено насправді номер телефону. Наприклад, що робити, якщо користувач не введе необхідні 10 цифр? Це має поєднуватися з хорошою перевіркою регулярних виразів.
Х'ю Джеффнер

108
Враховуючи питання про валідацію - це дійсно погана відповідь.
PlexQ

15
@PlexQ Я не згоден. Початкова проблема намагалася обробити перевірку номера телефону, оскільки вона намагалася обробити всі можливі варіанти форматування. Замість того, щоб намагатися вирішити все це, візьміть введення та «попередньо зніміть» його з усього пуху форматування, поки у вас є лише «число». Це вирішує дві проблеми - тестування результату тепер просте, і тепер ви можете гарантувати, що значення, виведені назад для відображення, можуть бути форматовані послідовно. Перший коментар до цієї відповіді про "Рукавички співучасника" - це добре прочитане ... іноді відповідь на проблему полягає в тому, щоб підійти до неї по-іншому.
сканліфф

29
Як, на біса, така відповідь, на яку голосують? Це нічого не підтверджує . Що гірше, що всі інші питання щодо підтвердження номера телефону посилаються на це ...
jlars62

303

Виявляється, є щось специфіка для цього, принаймні для Північної Америки, під назвою NANP .

Вам потрібно вказати саме те, що ви хочете. Що таке юридичні роздільники? Пробіли, тире та періоди? Не дозволено розміщувати роздільники? Чи можна змішувати роздільники (наприклад, + 0,111-222,3333)? Як обробляються розширення (наприклад, 111-222-3333 x 44444)? А як щодо спеціальних номерів, як 911? Чи буде код міста необов’язковим чи необхідним?

Ось регулярний вираз для 7 або 10 цифр із дозволеними розширеннями, роздільниками - пробіли, тире або періоди:

^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$

7
тут це без розділу розширень (я змушую своїх користувачів вводити ext в окреме поле): ^ (?: (?: \ +? 1 \ s * (?: [.-] \ s *)?)? (? : (\ s * ([2-9] 1 [02-9] | [2-9] [02-8] 1 | [2-9] [02-8] [02-9]) \ 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

18
Ось версія, яка відповідає лише десятизначним телефонним номерам (не 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})/
Брайан Армстронг

8
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})
Брук.

5
@StevenSoroka У мене протягом двох років на моєму столі була книга Джефрі Фрідля, оскільки регулярні висловлювання є основною частиною моєї роботи. Щоб зрозуміти регулярні вирази, потрібно багато часу. Іноді читачі цього веб-сайту просто шукають наявне рішення, а не пишуть своє, особливо в доменах з великою кількістю кутових справ, наприклад, представлення номерів телефонів.
Джастін Р.

7
@ fatcat1111 Я розумію це, але більшість відповідей тут - це "я теж" тип разових регулярних виразів, які, ймовірно, не відповідають жодному з ваших випадкових випадків. Потім вони потрапляють на всі веб-сайти, які я намагаюсь використовувати, і я не можу ввести свій поштовий індекс або номер телефону чи електронну адресу, оскільки хтось використав напівзапечатаний регулярний вираз (наприклад: + є дійсним символом в адресах електронної пошти ). Найкращі відповіді на цій сторінці вказують користувачів на бібліотеки, а не на вичерпані серветками регекси.
Стівен Сорока

298
.*

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

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

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

202
Я погоджуюся з настроями тут, але іноді приємно провести перевірку, коли номер телефону насправді буде використаний для чогось важливого в інтересах користувача . Найкращий приклад тут - авторизація кредитної картки на покупку. Якщо номер телефону невірний, аутентифікація може вийти з ладу.
Pointy

53
Якщо користувач не хоче вводити свій номер телефону, ви можете просто дозволити поле бути необов’язковим, але чи потрібно багато запитати користувача, щоб він ввів дійсний номер телефону, якщо він збирається ввести його?
Джоел МакБет

11
Також роль перевірки полягає в тому, щоб просто нагадати людям додавати коди районів тощо, які вони, можливо, не пам’ятають додати, але про які неможливо здогадатися після факту.
Бен Макінтайр

29
@Pointy Але перевірка регулярного вираження вам не допоможе. Єдиний і єдиний спосіб підтвердити дійсність, якщо номер телефону правильний - це фактично надіслати на нього повідомлення (у випадку мобільного) І переконатися, що користувач підтверджує, використовуючи якийсь код підтвердження. Це ви робите, коли важлива правильність числення. Все інше лише для зручності користувача, щоб захистити від деяких (але не всіх) помилок друку і нічого не підтверджує.
Алекс Б

14
Класно. Мій номер телефону 1 'АБО 1 = 1 - PWNED . Дивіться xkcd.com/327 та owasp.org/index.php/Testing_for_SQL_Injection_(OWASP-DV-005)
Аарон Ньютон

171

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

Наприклад, він визнає, що:

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

Якщо ви не впевнені, що ви завжди будете приймати номери з однієї мови, і вони завжди будуть в одному форматі, я настійно пропоную не писати для цього власний код і використовувати libphonebumber для перевірки та відображення телефонних номерів.


Зауваживши, що зараз також є порт "Перейти" за адресою: github.com/ttacon/libphonenumber
michaelhanson

Перевіряючи, чи це можливий номер, вам не потрібно вказувати код країни? Я використовую версію PHP, і якщо я ввожу британський номер на зразок (замініть 0 на справжніми цифрами), 07700000000я отримую Missing or invalid default region.помилку. Але якщо я вкажу код країни, він пройде.
BugHunterUK

FYI: Ця бібліотека не підтримує деякі країни, phpinterviewquestions.co.in/blog/ionic/…
sijo vijayan

1
@BugHunterUK (і кожен, хто стикається з цим питанням і дивується тим же), коли аналізує число, ви можете вказати очікуваний регіон, і бібліотека шукатиме неміжнародні номери в цьому регіоні. Якщо ви не вкажете, він відкине все, що не є дійсним міжнародним форматом.
IMSoP

Розгляньте github.com/nyaruka/phonenumbers, оскільки він став "офіційним" пакетом Go, рекомендованим Google, а не libphonenumber.
DeeZone

78

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

Чи можете ви, будь ласка, переформулювати фразу? Я не можу цього зрозуміти: "Легко обійтись, поки ви не видалите ^ і $, інакше я зможу його обійти за допомогою [111] [111] [1111]". Чи означає це, що він підтверджує "[111] [111] [1111]", коли ви приймаєте ^та $?
Ісмаїл Мігель

Я обійшов ваш регекс за допомогою [111] [111] [1111]та 111--111--1111до тих пір, поки я не видалив ^і $з нього.
bafromca

11
^^^ Це чудовий приклад того, чому нитки коментарів НЕ повинні йти в чат. Мені дуже цікаво, як вийшла ця розмова і мені потрібно знати, чи достатньо міцний цей ReGex для використання в моєму додатку. На жаль, чат-розмова зараз пропав.
Метт Кашатт

1
Якщо чесно, я не поїхав спілкуватися. Після того, як кілька разів просили пояснень, я залишився без інформації. Ви завжди можете спробувати самостійно з усіма видами номерів в Інтернеті, у різних форматах. Одне, що я спробував із цим, - це використовувати декілька телефонних номерів, але це не працює так добре, якщо у них є пробіли. І мені потрібно знайти рішення, щоб підрахувати кількість цифр і застосувати певну суму.
Ісмаїл Мігель

63

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

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 [$1-$2-$3]\n" if not defined $4;
                print "match [$1-$2-$3 $5]\n" if defined $4;
        }
        else
        {
                print "no match [$num]\n";
        }
}

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

Редагувати:

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

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

2
FYI відповідає також регулярний вираз: (4570457-6789що було б досить поширеною помилкою. Групи матчів теж перекошені: rubular.com/r/TaTP0mHL5c
SooDesuNe

@SooDesuNe Попередній перегляд (^|[^\d\n])(із увімкненим багаторядковим прапором) дозволяє уникнути загальної проблеми, гарантуючи, що не одразу передує щось числове.
Btown

Зауважте, що це орієнтація на Північну Америку - вона пропускає "44 7911 123456"
Бен Уілер,

43

Я відповів на це питання на інше питання SO, перш ніж вирішити також включити мою відповідь як відповідь на цю тему, тому що ніхто не звертався до того, як вимагати / не вимагати елементів, просто роздавав регулярні вирази: Regex працює неправильно, відповідає несподіваним речам

З моєї публікації на цьому веб-сайті я створив короткий посібник, щоб допомогти будь-кому створити власний регулярний вираз для власного потрібного формату телефонного номера, який я застережу (як я робив на іншому сайті), що якщо ви занадто обмежуючі, ви можете не отримати бажаних результатів, і немає рішення "один розмір, який відповідає всім", щоб прийняти всі можливі телефонні номери у світі - лише те, що ви вирішите прийняти як обраний формат. Використовуйте на свій страх і ризик.

Швидкий шпаргалка

  • Почніть вираз: /^
  • Якщо вам потрібно зайняти місце, скористайтеся: [\s]або\s
  • Якщо ви хочете вимагати дужок, використовуйте: [(]і [)]. Використання \(та\) некрасиво, і може зробити речі заплутаними.
  • Якщо ви хочете, щоб щось не було обов'язково, поставте ? його
  • Якщо ви хочете дефіс, просто введіть -або[-] . Якщо ви не ставите його першим чи останнім у серії інших символів, можливо, вам знадобиться уникнути цього: \-
  • Якщо ви хочете прийняти різні варіанти в слоті, поставте дужки навколо варіантів: [-.\s] знадобиться дефіс, період або пробіл. Знак питання після останньої дужки зробить усі ці додаткові для цього слота.
  • \d{3}: Потрібен 3-значний номер: 000-999. Стенограма для [0-9][0-9][0-9] .
  • [2-9] : Для цього слота потрібна цифра 2-9.
  • (\+|1\s)? : Прийміть "плюс" або 1 і пробіл (символ труби, | ",, є "або"), і зробіть це необов'язковим. Знак "плюс" повинен бути уникнути.
  • Якщо ви хочете, щоб конкретні номери відповідали слоту, введіть їх: [246]знадобиться 2, 4 або 6. [77|78]знадобиться 77 або 78.
  • $/ : Закінчення виразу

1
Це дуже корисно, але я сумніваюся і шукаю {min, max} вираз. Ви можете допомогти?
Атабой Йосиф

Якщо це одна цифра, про яку ми говоримо (і ви можете зрівняти її відповідно до цього), дивіться [2-9]блок, який я помістив туди. Це означає, що ваш хв 2, а максимум 9. Відрегулюйте відповідно.
vapcguy

30

Я написав simpliest (хоча мені не потрібна крапка в ньому).

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

Як було сказано нижче, він перевіряє лише символи, а не його структуру / порядок


38
це підтверджує тонни чисел, які є технічно недійсними. як, "- + () () ()) ()))". Навчіться читати регулярні вирази, щоб ви могли зрозуміти, що ви робите.
Стівен Сорока

3
@StevenSoroka технічно може призвести до безлічі випадків, але коли ми думаємо про те, щоб просто допомогти користувачеві уникнути поширених помилок з найпростішим можливим рішенням, це шлях: :)
happyhardik

2
це також збіг пробілу, порожня лінія
Васим А.

1
@HappyHardik. Справді. Простий та потужний, для базової перевірки, дозволяйте користувачеві вводити більше однієї крапки, тире, дужки або плюс.
dijipiji

Просто використовував це, і це неправильно в багатьох аспектах. Наприклад, номер телефону у Великобританії може починатися з +44, або нумеру телефону може бути (0) всередині нього. Але це не вірно згідно з вашим регулярним виразом. Я рекомендував би відповідь @Ismael Miguel. Це працює чудово, і я б рекомендував переглянути свою відповідь.
Stelios Voskos

22

Якщо ви просто хочете переконатися, що у вас немає випадкового сміття в полі (тобто від спамерів форми), цей регекс повинен зробити добре:

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

Зауважте, що в ньому немає жодних спеціальних правил щодо кількості цифр або яких чисел у цих цифрах, вони просто підтверджують, що лише цифри, дужки, тире, плюс, пробіл, фунт, зірочка, крапка, кома або літери e, x,t присутні.

Він повинен бути сумісним з міжнародними номерами та форматами локалізації. Чи передбачаєте ви необхідність дозволити квадратні, фігурні або кутові дужки для деяких регіонів? (наразі вони не включені).

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

І хоча вилучення всіх / більшості нечислових символів може працювати добре на стороні сервера (особливо якщо ви плануєте передати ці значення до дозвону), ви, можливо, не захочете обробляти дані користувача під час перевірки, особливо якщо ви хочете, щоб вони вносити виправлення в інше поле.


22

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


15

Ви переглядали RegExLib ?

Введення американського телефонного номера повернуло цілий список можливостей.


3
Це виглядає як чудовий спосіб інтегрувати незрозумілі помилки у свій код.
Том Лорд

12

Моя спроба необмеженого регексу:

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

Приймає:

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

Відхиляє:

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

Вам належить оздоровити для показу. Після перевірки це може бути число.


12

Я виявив, що це працює досить добре:

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

Він працює для таких форматів чисел:

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

Обов’язково використовуйте глобальні та багаторядкові прапори.

Посилання: http://www.regexr.com/3bp4b


11

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

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

Північна Америка відверта, і для міжнародної я вважаю за краще використовувати "ідіоматичний" зразок, який охоплює способи, якими люди визначають та запам'ятовують свої цифри:

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

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

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

Це може бути упередженим, оскільки мій досвід обмежений Північною Америкою, Європою та невеликою частиною Азії.


Я намагався реалізувати вищезазначене у своєму скрипті перевірки javascript, але я постійно отримую invalid quantifierпомилку. Будь-які ідеї щодо того, що я роблю неправильно?
Jannis

Я додам тривіальний випадок, коли телефон вказаний без символів, але, можливо, пробіли та код країни, в Європі характерні для місцевих та мобільних номерів: 676412342, 676 46 32 12, 676 463 212
rupps

11

Ось чудова картина, яка найбільше відповідає валідації, яку мені потрібно було досягти. Я не є оригінальним автором, але я вважаю, що це варто поділитися, оскільки я вважав, що ця проблема є дуже складною і без стислої або широко корисної відповіді.

Наступний регулярний вираз охопить широко використовувані комбінації цифр та символів у різних глобальних форматах телефонних номерів:

/^\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".
Джон Шнайдер

2
Помилковий позитив для напр. "------- ((((((55555555" або "99999999999999999999999"
mikep

Це не підтверджує число макдональдів Нідерланду +31 76 596 4192 (я тільки тестував випадкові числа)
BIOHAZARD

10

Моє відчуття кишечника підкріплюється кількістю відповідей на цю тему - що існує практично нескінченна кількість рішень цієї проблеми, жодне з яких не буде елегантним.

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

На мою думку, найелегантніше рішення - це підтвердження мінімальної довжини, не більше того.


Спробувавши ряд цих даних та переглянувши наявні дані та відгуки користувачів, я б схильний погодитися ...
Крістофер Кінг,

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

10

Це проста схема регулярного вираження для філіппінських номерів мобільних телефонів:

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

або

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

відповідатиме цим:

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

Перший буде відповідати БУДЬ-якому двозначному коду країни, а другий - виключно філіппінському коду країни.

Перевірте це тут: http://refiddle.com/1ox


Дякую. Як щодо стаціонарних номерів з кодом міста, таким як 028231234? Мені цікаво, чи є коди районів лише 2-3 цифри і чи завжди їм передує 0?
stormwild

9

Ось моя найкраща спроба поки що. Він обробляє формати вище, але я впевнений, що мені не вистачає інших можливих форматів.

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

9

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

Вам потрібно буде проаналізувати перші кілька цифр, щоб визначити, що таке код країни, а потім діяти по-іншому залежно від країни.

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

Ви правильно визначили, що це хитра проблема ...

-Адам


Не пропонується рішення. МОЖЛИВО. Тільки тому, що це хитро або складно, це не означає, що ви повинні просто кинути руки вгору.
Ерік Ходонський

7

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

Ось що я нещодавно використовував для клієнтського проекту, де нам довелося конвертувати всі телефонні номери у будь-якому форматі на тел: посилання.

Поки що він працює над усім, на що вони кинули, але якщо з’являються помилки, я оновлю цю відповідь.

Regex:

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

Функція PHP для заміни всіх телефонних номерів на тел: посилання (на випадок, коли хтось цікавий):

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

Цей регулярний вираз збігався +1 1234562222222222222222222222.
Varda Elentári

чому б просто не повернутися?
thexande

Помилковий позитив для "999999999999999999999999999999999999999"
Бен Вілер

6

Я вважаю, що номер :: Телефон :: США та Regexp :: Загальні (особливо джерело Regexp :: Загальні :: URI :: RFC2806 ) модулі Perl можуть допомогти.

Питання, мабуть, слід уточнити трохи детальніше, щоб пояснити мету перевірки чисел. Наприклад, 911 - дійсне число в США, але 911x не для жодного значення x. Це так, що телефонна компанія може підрахувати, коли ви закінчите набір номера. У цьому питанні є кілька варіацій. Але ваш регулярний вираз не перевіряє частину коду району, так що, здається, не викликає занепокоєння.

Як і перевірка адрес електронної пошти, навіть якщо у вас є дійсний результат, ви не можете знати, чи призначений він комусь, поки ви не спробуєте його.

Якщо ви намагаєтесь перевірити введення користувача, чому б не нормалізувати результат і не зробити це? Якщо користувач вводить число, яке ви не можете розпізнати як дійсне число, збережіть його як введене або викресліть недоступні символи. Кількість :: Телефон :: Нормалізувати модуль Perl може бути джерелом натхнення.


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

4

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

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


Перевірка? 123% $) *% () $ * () # 456 * () * $ # (* (# $ @ 8908 відповідатиме вашому запропонованому рішенню.
PlexQ

1
@PlexQ 555-123-1234, 07777777777, 90210, 01.01.1901 - користувачі винахідливі в утрамбовуванні сміття шляхом перевірки. Краще не відзначати тих, хто справді має деякі незвичайні дані, використовуючи занадто обмежувальну перевірку та повідомляючи їм, що вони помиляються.
ReactiveRaven

4

Зробіть заміну на форматування символів, а потім перевірте, чи залишилися вони на справжність телефону. У PHP,

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

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


3

Я вважав, що це щось цікаве. Я його не перевіряв, але виглядає, що він би спрацював

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

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

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

/* Usage Examples */

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

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

$number = '08008-555-555';

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

echo "<br />";

$number = '123-555-555';

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

echo "<br />";

$number = '1800-1234-5678';

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

echo "<br />";

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

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

echo "<br />";

$number = '1234567890';

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

4
Здається, ваше повідомлення вказує на те, що ви не написали цей код. Не хочете, будь ласка, посилаючись на джерело?
Аластер Ірвін


3

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

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

Вони навіть переглядають, як замаскувати введення телефонних номерів у своєму підручнику.


3

Ось такий, який добре працює в JavaScript. Це в рядку, тому що саме цього очікував віджет Dojo.

Він відповідає 10-значному номеру NANP у Північній Америці з додатковим розширенням. Пробіли, тире та періоди приймаються розмежувачами.

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

3

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

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

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

2

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

Кілька простих виразів perl можуть бути:

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

Використовуйте першу, щоб утримувати групи цифр разом, що може давати підказки щодо форматування. Використовуйте другий, щоб банально кинути всі нецифрові цифри.

Чи хвилюєтесь, що може знадобитися пауза, а потім більше клавіш? Або щось на кшталт 555-1212 (чекайте звукового сигналу) 123?


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

Повинен закінчуватися цифрою, може починатися з (або + або цифри, а може містити + - (або)


2

Для всіх, хто зацікавлений у тому, щоб зробити щось подібне з ірландськими номерами мобільних телефонів, ось простий спосіб досягти цього:

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

PHP


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

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

На цьому посиланні також є рішення JQuery.

Редагувати:

jQuery рішення:

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

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


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



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

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

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

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

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

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

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

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

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

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


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

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

     });

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

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

    });


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

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

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

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


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

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

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



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

   });


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

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

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

        default: break;
    }

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


});

Джерело .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.