Skip to content

有效电话号码

描述

给定一个包含电话号码列表(一行一个电话号码)的文本文件 file.txt,写一个 bash 脚本输出所有有效的电话号码。

你可以假设一个有效的电话号码必须满足以下两种格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)

你也可以假设每行前后没有多余的空格字符。

示例

输入:file.txt

987-123-4567
123 456 7890
(123) 456-7890
输出:有效的电话号码
987-123-4567
(123) 456-7890

题解

分析

这是一道简单的正则匹配题,有效号码含两种情况

  • xxx-xxx-xxxx
  • (xxx) xxx-xxxx

x 为一个数字,单独匹配两种情况

  • ^[0-9]{3}-[0-9]{3}-[0-9]{4}$
  • ^\([0-9]{9}\) [0-9]{3}-[0-9]{4}$

那么要包含两种情况,最简单的方式就是使用|连接两个正则表达式

  • ^[0-9]{3}-[0-9]{3}-[0-9]{4}$|^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$

但是显得有点冗长,可以把重复部分提取出来,仅仅对不一致的前半部分进行|匹配

  • ^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$

转义

注意号码信息中的括号()需要通过转义符\进行转义

实现

grep

#!/bin/bash
# Read from the file file.txt and output all valid phone numbers to stdout.

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

使用合并优化后的正则表达式

#!/bin/bash
# Read from the file file.txt and output all valid phone numbers to stdout.

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

到这其实还可以再简化,把[0-9]\d替换,只不过需要使用Perl脚本语言的格式,所以需要-P参数。

grep -P '^(\d{3}-|\(\d{3}\) )\d{3}-\d{4}$' file.txt

awk & sed

除了grep, awk 和 sed 同样可以完成任务,使用同样的正则表达式,只是打印输出的语法稍有不同。

sed -rn '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$/p' file.txt
awk '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-([0-9]{4})$/' file.txt

小结

擅用grep, sedawk可以解决很多文本编辑问题。不过关于正则表达式,不用的工具或者编程语言所用标准或有不同,需要注意下。

reference