Регулярное выражение для переформатирования номера телефона в США в Javascript


97

Я хочу переформатировать (заменить, а не проверять - есть много ссылок для проверки) номер телефона для отображения в 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
Вам также необходимо указать, как каждый из принятых форматов сопоставляется с целевым форматом, что совсем не очевидно, если входной параметр равен нулю. Если вы не хотите использовать дополнительное условие, чтобы отсеять этот случай.
Джон

Ответы:


240

Предполагая, что вам нужен формат " (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
К вашему сведению, это не работает для таких номеров, как + 1555-555-5555
Will

'' + 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 часов поиска я счастлив, что попробовал эту!
фунгусантракс

Я добавил скобки вокруг кода города, если это помогает:(${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. Это решение было разработано для текстового мыла, поскольку оно находится в строке меню и предоставляет раскрывающееся меню, в котором вы можете запускать действия по манипулированию текстом над тем, что выбрано курсором или что находится в буфере обмена.

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

Замена / поиск и замена # 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 цифры. Если в номере телефона нет символа (, он должен начинаться с трех цифр. Например, (308или 308.
  • \)?: Означает, что номер телефона может содержать необязательные символы )после первых трех цифр.
  • [- ]?: Далее номер телефона может иметь дефис ( -) )после первых трех цифр, если он присутствует.
  • (\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
Копирование материалов с других веб-сайтов, а затем даже отказ от
до Хельге

1
Извините, я понятия не имел, что мы должны разместить ссылку. Я думал, нам нужно просто дать ответы на опубликованные вопросы.
Bebu

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

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