我试图把一个全面的正则表达式放在一起来验证电话号码。理想情况下,它可以处理国际格式,但它必须处理美国格式,包括以下内容:
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 1-234-567-8901 x1234 1-234-567-8901 ext1234 1 (234) 567-8901 1.234.567.8901 1/234/567/8901 12345678901
我会用我目前的尝试来回答,但我希望有人有更好的和/或更优雅的东西。
当前回答
我相信Number::Phone::US和Regexp::Common(尤其是Regexp::Common::URI::RFC2806的源代码)Perl模块会有所帮助。
应该更详细地说明这个问题,以解释验证这些数字的目的。例如,911在美国是一个有效的号码,但911x不是x的任何值,这样电话公司就可以计算出你什么时候拨号。关于这个问题有几种不同的说法。但是您的正则表达式不检查区域代码部分,因此这似乎不是一个问题。
就像验证电子邮件地址一样,即使你有一个有效的结果,你也无法知道它是否分配给了某人,直到你尝试它。
如果您正在尝试验证用户输入,为什么不规范化结果并处理它呢?如果用户输入的数字您不能识别为有效数字,则将其保存为输入值或删除不可用字符。Number::Phone::Normalize Perl模块可能是灵感的来源。
其他回答
你看过RegExLib了吗?
输入一个美国的电话号码,你会发现很多可能性。
执行替换格式化字符,然后检查剩余的电话有效性。在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同样有效,但要简单得多。
下面是一个在JavaScript中运行良好的例子。它在一个字符串中,因为这是Dojo小部件所期望的。
它匹配10位北美NANP号码可选扩展。空格、破折号和句号是可接受的分隔符。
"^(\\(?\\d\\d\\d\\)?)( |-|\\.)?\\d\\d\\d( |-|\\.)?\\d{4,4}(( |-|\\.)?[ext\\.]+ ?\\d+)?$"
更好的选择……只要去掉输入中的所有非数字字符(除了“x”和前导的“+”符号),注意,因为英国人倾向于用非标准形式的+44(0)写数字……当要求使用国际前缀时(在这种特定情况下,应该完全丢弃(0))。
然后,你会得到这样的值:
12345678901
12345678901x1234
345678901x1234
12344678901
12345678901
12345678901
12345678901
+4112345678
+441234567890
然后,当你显示,重新格式化为您的心脏内容。如。
1 (234) 567-8901
1 (234) 567-8901 x1234
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
...
...
...