我试图把一个全面的正则表达式放在一起来验证电话号码。理想情况下,它可以处理国际格式,但它必须处理美国格式,包括以下内容:

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

我会用我目前的尝试来回答,但我希望有人有更好的和/或更优雅的东西。


当前回答

下面是一个在JavaScript中运行良好的例子。它在一个字符串中,因为这是Dojo小部件所期望的。

它匹配10位北美NANP号码可选扩展。空格、破折号和句号是可接受的分隔符。

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

其他回答

执行替换格式化字符,然后检查剩余的电话有效性。在PHP中,

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

打破像这样复杂的regexp同样有效,但要简单得多。

我相信Number::Phone::US和Regexp::Common(尤其是Regexp::Common::URI::RFC2806的源代码)Perl模块会有所帮助。

应该更详细地说明这个问题,以解释验证这些数字的目的。例如,911在美国是一个有效的号码,但911x不是x的任何值,这样电话公司就可以计算出你什么时候拨号。关于这个问题有几种不同的说法。但是您的正则表达式不检查区域代码部分,因此这似乎不是一个问题。

就像验证电子邮件地址一样,即使你有一个有效的结果,你也无法知道它是否分配给了某人,直到你尝试它。

如果您正在尝试验证用户输入,为什么不规范化结果并处理它呢?如果用户输入的数字您不能识别为有效数字,则将其保存为输入值或删除不可用字符。Number::Phone::Normalize Perl模块可能是灵感的来源。

我倾向于同意去掉非数字,只接受最好的。也许是为了确保至少有几个数字,尽管这确实禁止像字母电话号码“ASK-JAKE”这样的东西。

一些简单的perl表达式可能是:

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

使用第一个来保持数字组在一起,这可能会提供格式化线索。使用第二个来简单地丢弃所有非数字。

您是否担心可能需要暂停,然后输入更多的键?或者是555-1212(等哔声)123?

Java为有效的电话号码生成REGEX

另一种替代方法是让Java生成一个REGEX,该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("([\\(\\)])", "\\\\$1"))
        .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("([\\(\\)])", "\\\\$1"))
                .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
...
...
...
    pattern="^[\d|\+|\(]+[\)|\d|\s|-]*[\d]$" 
    validateat="onsubmit"

必须以数字结尾,可以以(或+或数字开头,并且可以包含+ -(或)