有效电话号码¶
描述¶
给定一个包含电话号码列表(一行一个电话号码)的文本文件 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
, sed
和 awk
可以解决很多文本编辑问题。不过关于正则表达式,不用的工具或者编程语言所用标准或有不同,需要注意下。