我试图把一个全面的正则表达式放在一起来验证电话号码。理想情况下,它可以处理国际格式,但它必须处理美国格式,包括以下内容:
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
我会用我目前的尝试来回答,但我希望有人有更好的和/或更优雅的东西。
当前回答
请注意,剥离()字符不适用于常见的英国号码的书写风格:+44(0)1234 567890,这意味着可以拨打国际号码: + 441234567890 或在英国拨打01234567890
其他回答
我在另一个SO问题上回答了这个问题,然后决定把我的答案也包括在这个线程上,因为没有人解决如何要求/不要求项目,只是分发正则表达式: 正则表达式工作错误,匹配意想不到的东西
从我在那个网站上的帖子中,我创建了一个快速指南,帮助任何人为自己想要的电话号码格式制作自己的正则表达式,我要警告(就像我在另一个网站上所做的那样),如果你限制太多,你可能不会得到想要的结果,并且没有“一宜之计”的解决方案来接受世界上所有可能的电话号码——只有你决定接受的格式作为你选择的格式。使用风险自负。
快速小抄
Start the expression: /^ If you want to require a space, use: [\s] or \s If you want to require parenthesis, use: [(] and [)] . Using \( and \) is ugly and can make things confusing. If you want anything to be optional, put a ? after it If you want a hyphen, just type - or [-] . If you do not put it first or last in a series of other characters, though, you may need to escape it: \- If you want to accept different choices in a slot, put brackets around the options: [-.\s] will require a hyphen, period, or space. A question mark after the last bracket will make all of those optional for that slot. \d{3} : Requires a 3-digit number: 000-999. Shorthand for [0-9][0-9][0-9]. [2-9] : Requires a digit 2-9 for that slot. (\+|1\s)? : Accept a "plus" or a 1 and a space (pipe character, |, is "or"), and make it optional. The "plus" sign must be escaped. If you want specific numbers to match a slot, enter them: [246] will require a 2, 4, or 6. (?:77|78) or [77|78] will require 77 or 78. $/ : End the expression
你会很难用一个简单的正则表达式处理国际号码,看看这篇关于国际(甚至北美)电话号码的困难的文章。
您需要解析前几位数字以确定国家代码,然后根据国家采取不同的操作。
除此之外——你给出的列表不包括另一种常见的美国格式——省略了首字母1。在美国,大多数手机都不需要这种功能,这将开始困扰年轻一代,除非他们拨打国际长途电话。
你已经正确地认识到这是一个棘手的问题。
亚当
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
...
...
...
这是一个简单的菲律宾手机号码的正则表达式模式:
((\+[0-9]{2})|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}
or
((\+63)|0)[.\- ]?9[0-9]{2}[.\- ]?[0-9]{3}[.\- ]?[0-9]{4}
将匹配这些:
+63.917.123.4567
+63-917-123-4567
+63 917 123 4567
+639171234567
09171234567
第一个将匹配任何两位数的国家代码,而第二个将匹配菲律宾国家代码。
在这里测试:http://refiddle.com/1ox
我相信Number::Phone::US和Regexp::Common(尤其是Regexp::Common::URI::RFC2806的源代码)Perl模块会有所帮助。
应该更详细地说明这个问题,以解释验证这些数字的目的。例如,911在美国是一个有效的号码,但911x不是x的任何值,这样电话公司就可以计算出你什么时候拨号。关于这个问题有几种不同的说法。但是您的正则表达式不检查区域代码部分,因此这似乎不是一个问题。
就像验证电子邮件地址一样,即使你有一个有效的结果,你也无法知道它是否分配给了某人,直到你尝试它。
如果您正在尝试验证用户输入,为什么不规范化结果并处理它呢?如果用户输入的数字您不能识别为有效数字,则将其保存为输入值或删除不可用字符。Number::Phone::Normalize Perl模块可能是灵感的来源。