美国电话号码正则校验:如何拒绝区号后无右括号带空格的无效号码
解决方案
核心逻辑
原有正则的问题是没有对「区号是否带括号」和「区号后的分隔符规则」做绑定,导致无括号的区号后可以随意匹配空格。我们可以把两种合法的区号格式拆成互斥分支,分别约束后续的分隔符规则,就能精准拦截目标无效号码。
修改后完整代码
import re def parse_us_phone(s): # 正则规则说明: # ^\s* 匹配开头可选空白字符 # (?: 非捕获分组,包裹两种合法区号格式 # \((\d{3})\)\s* 第一种:带括号的区号,匹配(xxx)后可接任意空白 # | 或 # (\d{3})(?:-|(?=\d)) 第二种:不带括号的区号,后面只能接横杠或直接接数字,禁止接空格 # ) # [ -]* 匹配两段号码中间可选的横杠/空格 # (\d{3}) 捕获中间3位交换码 # [ -]* 匹配两段号码中间可选的横杠/空格 # (\d{4}) 捕获最后4位线号 # \s*$ 匹配结尾可选空白字符 reg_ph = re.match(r'^\s*(?:\((\d{3})\)\s*|(\d{3})(?:-|(?=\d)))[ -]*(\d{3})[ -]*(\d{4})\s*$', s) if reg_ph: # 两个分支仅一个会捕获到区号,取非空值作为区号返回 area_code = reg_ph.group(1) or reg_ph.group(2) return (area_code, reg_ph.group(3), reg_ph.group(4)) else: raise ValueError('not a valid phone number')
验证效果
- 合法号码匹配测试
print(parse_us_phone('(916) 222-1111 ')) # 输出 ('916', '222', '1111') print(parse_us_phone(' 916-2221111 ')) # 输出 ('916', '222', '1111') print(parse_us_phone('9162221111')) # 输出 ('916', '222', '1111') print(parse_us_phone('(916)-2221111')) # 输出 ('916', '222', '1111')
- 无效号码拦截测试
parse_us_phone('916 111-2222') # 抛出 ValueError: not a valid phone number
内容的提问来源于stack exchange,提问作者Toly
相关产品推荐
相关产品推荐

