正则表达式:grep -E 与 grep元字符的区别

424 阅读2分钟

刷leecode,shell题如下:

给定一个包含电话号码列表(一行一个电话号码)的文本文件 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

新建一个文件,内容如下:

[root@localhost ~]# cat file.txt 
123-456-78907-34783
187-3381-3837
0312-215152
010-64535871
987-123-4567
123 456 7890
(123) 456-7890

我用了两种写法

这两种写法在""和''中对特殊字符有一定的区别,注意"\("的位置

[root@localhost ~]#  grep -E '^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$' file.txt
987-123-4567
(123) 456-7890


[root@localhost ~]# grep "^\(([0-9]\{3\}) \|[0-9]\{3\}-\)[0-9]\{3\}-[0-9]\{4\}$" file.txt 
987-123-4567
(123) 456-7890

区别如下

1. grep双引号中的"("就是字符的本意
[root@localhost ~]# grep "(" file.txt 
(123) 456-7890

2. egrep双引号中的"("存在特殊含义,需要转义才能表示字符的本意
[root@localhost ~]# grep -E "(" file.txt
grep: Unmatched ( or \(

[root@localhost ~]# grep -E "\(" file.txt
(123) 456-7890

egrep中的’E’表示将模式视为正则表达式。在Egrep中启用了“扩展正则表达式”缩写为“ERE”。egrep(与grep -E相同)将 +, ?, |, (, ) 作为元字符。

在基本的正则表达式(使用grep),元字符 ?, +, {, |, (, ) 失去了特殊的意义。如果你想用grep对待这些字符作为元字符,需要转义 ?, +, {, |, (,)。