使用egrep批量验证文件中邮箱的正则表达式问题排查
咱们来一步步拆解你这个egrep命令的问题,看看为啥会误匹配那些不符合规则的邮箱:
你的命令存在的几个关键错误:
正则未用引号包裹,导致shell篡改了你的规则
你写的正则没有用单/双引号括起来,shell会把\.+解析成.+(因为无引号环境下反斜杠会被当作转义符去掉)。原本你想匹配点号,结果变成了匹配任意一个或多个字符,这直接导致大量不符合的字符串被误匹配。缺少首尾锚定符,导致部分匹配也被选中
你的正则没有加^(字符串开头)和$(字符串结尾),egrep会默认匹配字符串中任意符合规则的子片段,而不是整个邮箱地址。比如2anell@utp.ac.pa里的anell@utp.ac.pa子片段符合规则(去掉转义问题后),所以整个字符串被误判为匹配。名字/姓氏的匹配范围太窄
你用[a-z]只匹配单个小写字母,但名字和姓氏显然是一个或多个字母组成的,应该用[a-z]+来匹配。点号的匹配逻辑错误
你用\.+匹配一个或多个点号,但需求里明确是名字和姓氏之间只有一个点号,应该用\.(单个转义后的点号)即可。域名部分的匹配完全错误
["utp.ac.pa"]是正则的字符集语法,意思是匹配u、t、p、.、a、c、"中的任意一个字符,而不是匹配完整的utp.ac.pa域名。另外域名里的.需要转义,因为正则中.是匹配任意字符的通配符。
修正后的正确命令:
把正则用单引号括起来,同时修正所有规则错误,最终命令如下:
egrep -E '^[a-z]+\.[a-z]+[0-9]*@utp\.ac\.pa$' test.txt
正则规则解释:
^:强制匹配字符串的开头,避免开头有无关字符(比如2anell@...这种)[a-z]+:匹配一个或多个小写字母(名字部分)\.:匹配名字和姓氏之间的那个点号(转义后表示字面量的点)[a-z]+:匹配一个或多个小写字母(姓氏部分)[0-9]*:匹配0个或多个数字(可选的重名后缀,允许没有数字)@utp\.ac\.pa:匹配固定的域名,每个.都转义成字面量点$:强制匹配字符串的结尾,避免结尾有多余字符
这样修改后,就能准确匹配anell.zheng@utp.ac.pa,同时排除test4@utp.ac.pa(缺少名字姓氏间的点号)、2anell@utp.ac.pa(开头有数字且无点号分隔)这类不符合规则的邮箱了。
内容的提问来源于stack exchange,提问作者user9712208

