正则表达式出错,匹配了意外的内容

1 投票
1 回答
1434 浏览
提问于 2025-04-18 16:24

我有一个正则表达式:

[\(\+\[]?[0-9]([\-\)\.\/-\]]?\s?\(?[0-9\s\)]){8,20}?

这个正则表达式应该只匹配电话号码,但实际上它还匹配了一些其他的东西,比如:

[95.86.22.137]
95.86.22.137
(192.168.1.94)
274.1363525390625px;">
2014-8-720:32:45

有人能帮我修正这个正则表达式吗?

1 个回答

2

如果你想把这件事做好,我建议你从头开始,首先明确你想要匹配的格式,而不是你想排除的内容。你需要从“我想要什么?”这个角度出发,而不是“我想排除什么?”这样做能帮助你更清晰地找到需要的内容,从而排除那些不必要的选项。

首先,你得决定什么样的号码算是“有效的电话号码”。即使在北美号码计划(NANP)中,也有几种不同的格式,比如:

  • XXX-XXX-XXXX 或者
  • XXX XXX-XXXX 或者
  • 1-XXX-XXX-XXXX 或者
  • (XXX) XXX-XXXX 或者
  • +(XXX) XXX-XXXX 或者
  • 1 (XXX) XXX-XXXX

这些都是有效的号码,所以你需要决定你接受哪种格式。此外,世界其他地方的号码格式也各不相同,长度从9位(如葡萄牙)到13位(如韩国)不等,包括国家和国际代码。所以你需要考虑:

  • 你只接受NANP的号码,还是也接受其他标准之外的号码?
  • 你会接受“+”符号,还是要求用户输入国际代码?如果你要求输入代码,用户输入的国家代码是否有固定的位数?如果他们输入了代码,你的正则表达式能处理(如果可以接受)还是会标记为错误(如果不可以接受)?
  • 你会强制要求区号用括号括起来,还是允许括号(让括号变成可选),或者直接不接受括号?

关于最后一点,不同国家的号码中括号的位置也不同,比如墨西哥的区号是2位(而且不在NANP中)。

记住,每次你做出这样的决定,要求某个字符存在时,你就会排除其他可能有效的电话号码,除非你也允许其他有效字符在那个位置出现。这就是为什么没有一种通用的解决方案适合所有情况。因此,很多人会建议你直接去掉“+”、“(”、“)”、“-”,然后只计算数字。但如果你认为NANP号码中的“1”是必须的,而有人没有输入(因为在NANP中通常是可选的),或者不同国家的号码位数不同——即使在同一个国家,比如新西兰,这种方法就会失效。

有一个所谓的综合指南: 一个全面的电话号码验证正则表达式

但我发现它在处理如何让用户输入“+”与“1”以及空格(对于NANP号码)、如何强制使用括号、连字符等方面非常不足。它提供了正则表达式,而不是解释如何达到这个目的。因此我在这里写下我的“博客”,作为答案。

以下是我使用的严格的NANP正则表达式,它会接受:

  • +(XXX) XXX-XXXX
  • 1 (XXX) XXX-XXXX
  • (XXX) XXX-XXXX

它要求使用括号和连字符,我认为对于NANP号码来说,这样做既灵活又符合标准。幸运的是,我不处理国际(NANP以外)号码:

/^(\+|1\s)?[(][2-9]\d{2}[)][\s][2-9]\d{2}-\d{4}$/

/^ = 匹配单词的开始;基本上表示表达式的开始

(\+|1\s)? 组

  • 括号用于分隔组,表示组内的任何字符都是可选的,后面的?表示可选,并允许“或”条件(见管道符号)
  • \+ = 转义的“+”,用于匹配加号(必须转义,因为它在正则表达式中是一个关键字符,使用反斜杠)
  • | = 管道符号,表示应该匹配左边或右边的内容
  • 1\s = 要求数字1和一个空格。空格不是通过[]强制的——虽然我看到其他帖子似乎表明可以,但对我来说不管用,应该是\s

[(] = 这表示开放括号是必须的。

[2-9]\d{2} 组

  • [2-9] = 这个表达式匹配2到9的数字。在NANP中,区号的开头(前3个数字)和电话交换的开头(后3个数字)不能是0或1。
  • \d{2} = 这表示允许2位数字,范围是0-9。这是[0-9][0-9]的简写。

对于000-999的三位数字组,你只需写:\d{3}

[)] = 这表示闭合括号是必须的。

[\s] = 这将要求有一个空格。

[2-9]\d{2}-\d{4} 组

  • 这一部分,在连字符之前,和之前的一样。
  • 设置连字符将使其成为必需。如果你写-?,它就是可选的。
  • \d{4} = 这表示允许4位数字,范围是0-9。这是[0-9][0-9][0-9][0-9]的简写。

$/ = 表示匹配到单词的结尾;基本上表示表达式的结束。

希望这能帮助你构建你的表达式。

撰写回答