正则表达式在Javascript中重新格式化美国电话号码

时间:2011-12-02 14:50:40

标签: javascript regex

我正在寻找重新格式化(替换,而不是验证 - 有许多用于验证的参考)电话号码以便在Javascript中显示。以下是一些数据的示例:

  • 123 4567890
  • (123)456-7890
  • (123)456-7890
  • 123 456 7890
  • 123.456.7890
  • (空白/空)
  • 1234567890

有一种简单的方法可以使用正则表达式来执行此操作吗?我正在寻找最好的方法来做到这一点。还有更好的方法吗?

我想将数字重新格式化为以下内容:(123) 456-7890

14 个答案:

答案 0 :(得分:133)

假设您需要格式“(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"

答案 1 :(得分:26)

可能的解决方案:

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

答案 2 :(得分:18)

var x = '301.474.4062';

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

工作示例here

答案 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

的标准格式

答案 4 :(得分: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

答案 5 :(得分:1)

这个答案是从数学的答案中借来的。主要区别在于它接受部分输入的电话号码并格式化输入的部分。

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

答案 6 :(得分:1)

我已经扩展了David Baucum's answer,以包括对最大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;

答案 7 :(得分: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 = '';        
    }
})

答案 8 :(得分:1)

2021

libphonenumber-js

示例

import parsePhoneNumber from 'libphonenumber-js'

const phoneNumber = parsePhoneNumber('+12133734253')

phoneNumber.formatInternational() === '+1 213 373 4253'
phoneNumber.formatNational() === '(213) 373-4253'
phoneNumber.getURI() === 'tel:+12133734253'

答案 9 :(得分:0)

这是一个接受电话号码和带扩展名的电话号码的人。

Status

答案 10 :(得分:0)

向后思考

仅使用最后一位数字(最多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

答案 11 :(得分:0)

上述解决方案非常出色,尤其是在使用Java的情况下,并且遇到的数字超过10位的数字更多,例如国际代码前缀或其他扩展名。此解决方案是基本的(我是regex的初学者),并且考虑到了美国电话号码,仅适用于只有10个数字且可能带有某些格式化字符的字符串,或者根本没有格式化字符(仅10个数字) )。因此,我建议将此解决方案仅用于半自动应用程序。我个人更喜欢将数字存储为仅10个数字,而无需设置格式字符,但是我也希望能够将电话号码转换或清除为普通格式,而普通人和应用程序/电话会立即识别出这种格式。

我碰到这篇文章,寻找可以与具有PCRE Regex功能(但没有Java函数)的文本清洁器应用程序一起使用的功能。我将在这里发布此文章,以供那些可以使用简单的正则表达式解决方案的人使用,该解决方案可以在各种文本编辑器,清理器,扩展器甚至某些剪贴板管理器中使用。我个人使用Sublime和TextSoap。此解决方案专为Text Soap而开发,因为它位于菜单栏中,并提供一个下拉菜单,您可以在其中针对光标选择的内容或剪贴板中的内容触发文本操作。

我的方法本质上是两个替换/搜索和替换正则表达式。每个替换搜索和替换都涉及两个正则表达式,一个用于搜索,一个用于替换。

替换/搜索并替换#1

  • 第一个替换/搜索和替换功能将非数字的数字从原本的10位数字剥离为10位字符串。

首次替换/ 搜索正则表达式:\D

  • 此搜索字符串匹配不是数字的所有字符。

第一次替换/ 替换正则表达式:“”(什么都没有,甚至没有空格)

  • 将替代字段完全保留为空白,不应存在任何空格,包括空格。这将导致所有匹配的非数字字符被删除。在执行此操作之前,您应该输入10位数字+格式化字符,然后输入10位数字+格式化字符。

替换/搜索并替换#2

  • 该操作的第二个替换/搜索和替换 search 部分捕获区域代码$1的组,捕获第二组三个数字$2的捕获组,以及最后一组四个数字$3的最后一个捕获组。该操作的替代部分的正则表达式在捕获的数字组之间插入美国电话号码格式。

第二次替换/ 搜索正则表达式:(\d{3})(\d{3})(\d{4})

第二次替换/ 替换正则表达式:\($1\) $2\-$3

  • 反斜杠\转义特殊字符() (<-空白)和-,因为我们正在插入它们在捕获组$1$2$3中捕获的号码之间,用于美国电话号码格式化。

  • 在TextSoap中,我创建了一个自定义清理程序,其中包括两个替换操作操作,因此在实践中,它感觉与执行脚本相同。我确信可以改进此解决方案,但我希望复杂性会大大提高。如果有人要添加此解决方案的改进版本,可以作为学习的经验。

答案 12 :(得分:0)

基于 David Baucum 的回答 - 这是一个尝试改进自动替换的版本,例如在 React onChange 事件处理程序中:

function formatPhoneNumber(phoneNumber) {
  const cleanNum = phoneNumber.toString().replace(/\D/g, '');
  const match = cleanNum.match(/^(\d{3})(\d{0,3})(\d{0,4})$/);
  if (match) {
    return '(' + match[1] + ') ' + (match[2] ? match[2] + "-" : "") + match[3];
  }
  return cleanNum;
}

//...

onChange={e => setPhoneNum(formatPhoneNumber(e.target.value))}

只要有 3 个数字,它就会插入 (###),然后它会继续跟随 RegEx 直到它看起来像这样 (###) ###-####

答案 13 :(得分:-1)

对于美国电话号码

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

让我们将这个正则表达式划分为较小的片段,以便于理解。

  • /^\(?:表示电话号码可以以可选(开头。
  • (\d{3}):在可选(之后,必须有3位数字。如果电话号码没有(,则必须以3位数字开头。例如。 (308308
  • \)?:表示电话号码前3位后可以选择)
  • [- ]?:接下来,如果存在-或前3位数后,电话号码可以有一个可选的连字符())。
  • (\d{3}):然后必须再增加3位数字。 E.g (308)-135308-135308135
  • [- ]?:在第二组3位数后,电话号码可以有另一个可选的连字符(-)。 E.g (308)-135-308-135-308135-
  • (\d{4})$/:最后,电话号码必须以四位数结尾。例如(308)-135-7895308-135-7895308135-78953081357895

    参考:

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