题目描述

✅ 193. 有效电话号码

image-20260928233520576

题意分析

file.txt 每行是一个待校验的电话号码,合法格式只有 xxx-xxx-xxxx 与 (xxx) xxx-xxxx 两种,每个 x 都是一位数字。题目已保证每行没有前后多余空白。

校验的是整行格式:数字位数、括号、空格与连字符都必须精确匹配。即使某一行内部包含合法号码,只要还夹带其他字符,就不应输出。

两种格式共享后半段 三位数字-四位数字,不同的只是区号前缀。可以把前缀写成两个分支,再接上同一份后缀,用一次 grep 完成筛选。

解法:grep 扩展正则匹配整行

核心思路

[!blue]

用 grep -E 启用扩展正则表达式,表达式的结构是 ^(前缀一|前缀二)公共后缀$。

  • [0-9]{3}- 表示三位数字后紧跟一个连字符,对应无括号的区号。
  • \([0-9]{3}\) 表示左括号、三位数字、右括号,再加一个普通空格。正则中不转义的括号用于分组,因此匹配号码里的字面括号要写成 \(、\)。
  • [0-9]{3}-[0-9]{4} 是两种格式共同的剩余部分,要求数字位数分别为 3 和 4。

最外侧的 ^、$ 分别要求从行首开始、在行尾结束。前缀分支先放在同一组内,这两个锚点才会同时约束两种格式。表达式使用单引号传给 shell,让其中的反斜杠和其他正则字符保持原样。

grep 会按输入顺序直接输出匹配的原始行,不需要再解析或重新拼接号码。

解题步骤

  1. 将两种区号写成一个用 | 分开的分组。
  2. 在分组后追加公共的三位数字、连字符与四位数字。
  3. 用行首、行尾锚点限定整个表达式,只允许整行符合格式。
  4. 使用 grep -E 对文件逐行筛选,原样输出命中的行。

代码实现

grep -E '^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$' file.txt

复杂度分析

  • 时间复杂度:$O(N)$,$N$ 是文件总字符数。正则模式长度固定,扫描输入的开销为线性。
  • 空间复杂度:按逐行处理计为 $O(L)$,$L$ 是最长输入行的长度;模式本身只占常数空间,不需要把全部文件读入内存。

关键点总结

[!green]

  • {3} 和 {4} 限定准确位数,不能写成任意长度的数字序列。
  • 括号后的普通空格属于格式,必须恰好出现一次,不能用任意空白代替。
  • 分组括号不转义,输入号码里的字面括号要转义,两者用途不同。
  • [0-9] 与 grep -E 的扩展正则语法匹配;不要把其他正则方言中的 \d 直接搬过来。

易错点总结

[!yellow]

  • 漏掉首尾锚点:会接受只在局部包含合法号码的非法行。
  • 将分支直接写在两个锚点之间却不分组:^A|B$ 的行首只约束 A,行尾只约束 B,不能代表整行匹配 A 或 B。
  • 把号码中的括号当成正则分组:输入里的字面括号就不再被要求出现,匹配含义会改变。
  • 省略括号后的空格,或允许多个空格:都会偏离题目要求的 (xxx) xxx-xxxx。
  • 令括号或连字符可选:会额外接受题目没有规定的混合格式。
  • 漏写 -E:基本正则与扩展正则对分组、分支和重复次数的写法不同,不能混用。

相似题目

题目 难度 关联与区别
65. 有效数字 困难 同样验证整个字符串是否满足指定语法,原题是数值格式,本题是电话号码的两种固定格式。
468. 验证IP地址 中等 同样精确校验数字段、分隔符及整体格式,IP题还需检查每段数值范围。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/10292044
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!