Регулярний вираз для переформатування американського телефонного номера в Javascript


98

Я хочу переформатувати (замінити, а не перевірити - є багато посилань для перевірки) номер телефону для відображення в Javascript. Ось приклад деяких даних:

  • 123 4567890
  • (123) 456-7890
  • (123)456-7890
  • 123 456 7890
  • 123.456.7890
  • (порожній / нульовий)
  • 1234567890

Чи існує простий спосіб використовувати регулярний вираз для цього? Я шукаю найкращий спосіб зробити це. Чи є кращий спосіб?

Я хочу переформатувати номер так: (123) 456-7890


3
І який із них є вашим цільовим форматом?
До Хелге

Цей: (123) 456-7890
Метт К,

3
Я б сказав, що просто видаліть усі нецифрові символи, тоді візьміть три підрядки.
Wiseguy

2
@Wiseguy, будь ласка, опублікуйте це як відповідь (із прикладом), оскільки це дійсно те, що повинен робити OP.
Брайан Дрісколл

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

Відповіді:


242

Якщо припустити, що вам потрібен формат " (123) 456-7890":

function formatPhoneNumber(phoneNumberString) {
  var cleaned = ('' + phoneNumberString).replace(/\D/g, '')
  var match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/)
  if (match) {
    return '(' + match[1] + ') ' + match[2] + '-' + match[3]
  }
  return null
}

Ось версія, яка дозволяє додатковий +1міжнародний код:

function formatPhoneNumber(phoneNumberString) {
  var cleaned = ('' + phoneNumberString).replace(/\D/g, '')
  var match = cleaned.match(/^(1|)?(\d{3})(\d{3})(\d{4})$/)
  if (match) {
    var intlCode = (match[1] ? '+1 ' : '')
    return [intlCode, '(', match[2], ') ', match[3], '-', match[4]].join('')
  }
  return null
}
formatPhoneNumber('+12345678900') // => "+1 (234) 567-8900"
formatPhoneNumber('2345678900')   // => "(234) 567-8900"

2
Ідеально; Дякую! Однак я змінив return (!m) ? nullна return (!m) ? ""після додавання цієї функції.
Matt K

2
Гарний урок, як підходити до проблеми. Я намагався подумати, як зрівняти всі можливі випадки - ти усуваєш нерелевантне і перевіряєш, чи є збіг. Дуже хороша.
Jkleg

2
FYI це не працює для чисел , як + 1555-555-5555
Воля

'' + phoneNumberStringце те саме, що phoneNumberString... Це вже рядок.
YungGun

@YungGun, якщо хтось не викликає функцію з номером, наприкладformatPhoneNumber(8001231234)
maerics

32

Можливе рішення:

function normalize(phone) {
    //normalize string and remove all unnecessary characters
    phone = phone.replace(/[^\d]/g, "");

    //check if number length equals to 10
    if (phone.length == 10) {
        //reformat and return phone number
        return phone.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");
    }

    return null;
}

var phone = '(123)4567890';
phone = normalize(phone); //(123) 456-7890

27

var x = '301.474.4062';
    
x = x.replace(/\D+/g, '')
     .replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');

alert(x);


1
Дякую Шон, мені подобається ваше коротке просте вбудоване рішення.
user752746 02

1
Дякую за це! Я змінив його на " x = x.replace(/[^\d]+/g, '') .replace(/(\d{1})(\d{3})(\d{3})(\d{4})/, '+$1 ($2) $3-$4');працюючи", наприклад, додавши "+1" перед номером телефону
Greg A,

Дякую! це якраз мені потрібно
Альберт Ідальго,

8

Ця відповідь запозичена з відповіді maerics. Він відрізняється насамперед тим, що приймає частково введені номери телефонів та форматує введені частини.

phone = value.replace(/\D/g, '');
const match = phone.match(/^(\d{1,3})(\d{0,3})(\d{0,4})$/);
if (match) {
  phone = `${match[1]}${match[2] ? ' ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}`;
}
return phone

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

Я додав дужки навколо коду міста, якщо це допомагає:(${match[1]}${match[2] ? ') ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}
Пітер Холлінгсворт

Насправді проблема полягає в тому, що ви не можете повернути пробіл через '-' або пробіл із середнього рядка. Вам потрібно запобігти переформатування, коли користувач здійснює зворотний інтервал (наприклад, newstring.length < oldstring.lengthАБО для відстеження позиції курсора та з'ясування того, коли користувач щойно повернув інтервал перед цими роздільниками, наприкладif (cursorPosition === 4 && numericString.length > 3)
Пітер Холлінгсворт

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

5

Я використовую цю функцію для форматування американських номерів.

function formatUsPhone(phone) {

    var phoneTest = new RegExp(/^((\+1)|1)? ?\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})( ?(ext\.? ?|x)(\d*))?$/);

    phone = phone.trim();
    var results = phoneTest.exec(phone);
    if (results !== null && results.length > 8) {

        return "(" + results[3] + ") " + results[4] + "-" + results[5] + (typeof results[8] !== "undefined" ? " x" + results[8] : "");

    }
    else {
         return phone;
    }
}

Він приймає майже всі мислимі способи написання американського телефонного номера. Результат відформатовано до стандартної форми (987) 654-3210 x123


3

мислення назад

Візьміть лише останні цифри (до 10), ігноруючи першу "1".

function formatUSNumber(entry = '') {
  const match = entry
    .replace(/\D+/g, '').replace(/^1/, '')
    .match(/([^\d]*\d[^\d]*){1,10}$/)[0]
  const part1 = match.length > 2 ? `(${match.substring(0,3)})` : match
  const part2 = match.length > 3 ? ` ${match.substring(3, 6)}` : ''
  const part3 = match.length > 6 ? `-${match.substring(6, 10)}` : ''    
  return `${part1}${part2}${part3}`
}

приклад введення / виводу під час введення

formatUSNumber('+1333')
// (333)

formatUSNumber('333')
// (333)

formatUSNumber('333444')
// (333) 444

formatUSNumber('3334445555')
// (333) 444-5555

1
var numbers = "(123) 456-7890".replace(/[^\d]/g, ""); //This strips all characters that aren't digits
if (numbers.length != 10) //wrong format
    //handle error
var phone = "(" + numbers.substr(0, 3) + ") " + numbers.substr(3, 3) + "-" + numbers.substr(6); //Create format with substrings

1

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

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

//format text input as phone number (nnn) nnn-nnnn
$('.myPhoneField').on('input', function (e){
    var $phoneField = e.target;
    var cursorPosition = $phoneField.selectionStart;
    var numericString = $phoneField.value.replace(/\D/g, '').substring(0, 10);

    // let user backspace over the '-'
    if (cursorPosition === 9 && numericString.length > 6) return;

    // let user backspace over the ') '
    if (cursorPosition === 5 && numericString.length > 3) return;
    if (cursorPosition === 4 && numericString.length > 3) return;

    var match = numericString.match(/^(\d{1,3})(\d{0,3})(\d{0,4})$/);
    if (match) {
        var newVal = '(' + match[1];
        newVal += match[2] ? ') ' + match[2] : '';
        newVal += match[3] ? '-' + match[3] : '';

        // to help us put the cursor back in the right place
        var delta = newVal.length - Math.min($phoneField.value.length, 14);      
        $phoneField.value = newVal;
        $phoneField.selectionEnd = cursorPosition + delta;
    } else {
        $phoneField.value = '';        
    }
})

0

Ось такий, який приймає як номери телефонів, так і номери телефонів із розширеннями.

function phoneNumber(tel) {
var toString = String(tel),
    phoneNumber = toString.replace(/[^0-9]/g, ""),
    countArrayStr = phoneNumber.split(""),
    numberVar = countArrayStr.length,
    closeStr = countArrayStr.join("");
if (numberVar == 10) {
    var phone = closeStr.replace(/(\d{3})(\d{3})(\d{4})/, "$1.$2.$3"); // Change number symbols here for numbers 10 digits in length. Just change the periods to what ever is needed.
} else if (numberVar > 10) {
    var howMany = closeStr.length,
        subtract = (10 - howMany),
        phoneBeginning = closeStr.slice(0, subtract),
        phoneExtention = closeStr.slice(subtract),
        disX = "x", // Change the extension symbol here
        phoneBeginningReplace = phoneBeginning.replace(/(\d{3})(\d{3})(\d{4})/, "$1.$2.$3"), // Change number symbols here for numbers greater than 10 digits in length. Just change the periods and to what ever is needed. 
        array = [phoneBeginningReplace, disX, phoneExtention],
        afterarray = array.splice(1, 0, " "),
        phone = array.join("");

} else {
    var phone = "invalid number US number";
}
return phone;
}

phoneNumber("1234567891"); // Your phone number here

0

Ці функції можна використовувати для перевірки дійсних номерів телефонів та їх нормалізації:

let formatPhone = (dirtyNumber) => {
 return dirtyNumber.replace(/\D+/g, '').replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
}

let isPhone = (phone) => {
   //normalize string and remove all unnecessary characters
   phone = phone.replace(/\D+/g, '');
   return phone.length == 10? true : false;
}

0

Я розширив відповідь Девіда Бакума, включаючи підтримку розширень довжиною до 4 цифр. Він також включає дужки, запитані в оригінальному питанні. Це форматування працюватиме під час введення тексту в поле.

phone = phone.replace(/\D/g, '');
const match = phone.match(/^(\d{1,3})(\d{0,3})(\d{0,4})(\d{0,4})$/);
if (match) {
    phone = `(${match[1]}${match[2] ? ') ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}${match[4] ? ' x' : ''}${match[4]}`;
}
return phone;

0

Наведені вище рішення є кращими, особливо якщо використовується Java, і зустрічається більше номерів із понад 10 цифр, таких як префікс міжнародного коду або додаткові номери номерів. Це рішення є базовим (я новачок у світі регулярних виразів) і розроблено з урахуванням телефонних номерів США і корисно лише для рядків із лише 10 числами, можливо, з деякими символами форматування, або, можливо, без символів форматування (лише 10 цифр ). Як такий, я рекомендую це рішення лише для напівавтоматичних застосувань. Я особисто вважаю за краще зберігати номери як лише 10 чисел без форматування символів, але я також хочу мати можливість конвертувати або очистити телефонні номери у стандартний формат, як звичайні люди, і програми / телефони розпізнаватимуть їх миттєво за бажанням.

Я натрапив на цю публікацію, шукаючи щось, що я міг би використати з додатком для очищення тексту, який має можливості PCRE Regex (але без функцій Java). Я опублікую це тут для людей, які можуть використовувати просте чисте рішення Regex, яке може працювати в різних редакторах тексту, засобах очищення, розширювачах або навіть у деяких менеджерах буфера обміну. Я особисто використовую Sublime і TextSoap. Це рішення було розроблено для Text Soap, оскільки воно живе в рядку меню та містить спадне меню, де ви можете запускати дії з маніпулювання текстом над тим, що вибрано курсором або що є в буфері обміну.

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

Заміна / пошук і заміна # 1

  • Перша заміна / пошук і заміна позбавляє нечислові числа з 10-значного числа в інший рядок у 10-значний рядок.

Перша заміна / регулярний вираз пошуку :\D

  • Цей рядок пошуку відповідає всім символам, що не є цифрою.

Перша заміна / Заміна регулярного виразу: "" (нічого, навіть пробіл)

  • Залиште поле заміни повністю порожнім, не повинно бути пробілів, включаючи пробіли. Це призведе до видалення всіх відповідних нецифрових символів. До цієї операції вам слід було ввести 10 цифр + символів форматування і вийти з 10 цифрами без форматування символів.

Заміна / пошук і заміна # 2

  • Друга заміна / пошук і заміна пошук частини операції захоплення групи для коду області $1, що уловлює групи для другого набору з трьох чисел $2, а останній захоплення групи за останній набір з чотирьох чисел $3. Регулярний вираз для замісної частини операції вставляє форматування телефонного номера США між захопленою групою цифр.

Друга заміна / регулярний вираз пошуку :(\d{3})(\d{3})(\d{4})

Друга заміна / Заміна регулярного виразу:\($1\) $2\-$3

  • Зворотний слеш \екранує спеціальні символи (, ), (<-whitespace), і -так як ми вставляючи їх між нашими захопленими числами в групах захоплення $1, $2і $3для цілей форматування номера телефону в США.

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


-2

Для телефонних номерів США

/^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/

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

  • /^\(?: Означає, що номер телефону може починатися з необов’язкового (.
  • (\d{3}): Після необов’язкового (повинні бути 3 цифрові цифри. Якщо на телефонному номері немає (, він повинен починатися з 3 цифр. Наприклад, (308або 308.
  • \)?: Означає, що номер телефону може бути необов’язковим )після перших 3 цифр.
  • [- ]?: Далі номер телефону може мати необов’язковий дефіс ( -) після )наявності або після перших 3 цифр.
  • (\d{3}): Тоді мають бути ще 3 цифрові цифри. Наприклад, (308)-135або 308-135або308135
  • [- ]?: Після другого набору з 3 цифр номер телефону може мати ще один додатковий дефіс ( -). Наприклад, (308)-135-або 308-135-або308135-
  • (\d{4})$/: Нарешті, номер телефону повинен закінчуватися чотирма цифрами. Наприклад, (308)-135-7895або 308-135-7895або 308135-7895або 3081357895.

    Довідково:

http://www.zparacha.com/phone_number_regex/


1
Копіювання матеріалів з інших веб-сайтів, а потім навіть не розміщення посилання є досить поганою поведінкою: zparacha.com/phone_number_regex
до Хелге

1
Вибачте, я не уявляв, що ми повинні розмістити посилання. Я думав, що ми повинні просто дати відповіді на опубліковані запити.
Бебу

5
Ні разу не нормально , щоб зробити ще один чий вигляд роботи , як свій власний. Наступного разу пам’ятайте, що в публікації посилань немає нічого поганого, але копіювання (особливо без надання посилання) - ні. І у вас завжди є можливість редагувати свою відповідь.
До Хельге

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