首页 > 编程知识 正文

邮箱地址正则表达式,php中正则表达式验证

时间:2023-05-05 12:37:28 阅读:51164 作者:4782

1,在github上力推学习正则的项目

2 .一般邮箱格式

1,数字@数字.com: 111222335556666@163.com

2,数字,字母下划线@数字|字母.com:Zhangsan_123@163(QQ ).com

3,数字,字母,下划线@数字,字母,中线-.com:zhangsan _ 123 @ company-China.com

补充说明:为了便于理解以下内容,假设上述邮箱字符串被分割如下。

1 )第一部分: @符号前的内容

2 )第2部分) @符号后、符号前的部分

3 )第3部分) .符号之后的部分)上述链接格式以顶级域名com结尾,但不排除出现类似.com.cn的结构)。

3、正则解析

3.0、前言

1 )根据每个人的思维模式、理解能力等因素,在参考私人教程、上述推荐的github项目等资料的基础上,有了初步的基础后,可以参考本文,进一步借鉴请认真考虑我的提案。

2、本文适合正则初学者阅读; 还是为了引导初学者在学习过程中如何思考结构,优化正则表达式; 本文所用的例子并不一定涵盖现实中的所有邮箱格式。

因此,在阅读期间,请考虑一下本文没有提到的地方,以及该如何进行优化,并感谢您在以下信息中指出。

3、正文有点长,有时间最好操作。

4 )有些元字符偷懒,所以不在列表中。 请综合参考各方面的资料。

3.1、考核问题:如何匹配数字或字母?

1,能做的学生请通过

2、相关元字符:

d -表示[0-9]的整数数字;

w -显示字母、数字和下划线

-表示出现在符号(即符号前面的子表达式)必须至少出现一次。

-表示出现在符号前面的子表达式必须出现0次以上

? -表示出现在字符前面的子表达式出现0次或1次

^ -与输入字符的开始位置一致

$ -匹配输入字符的结束位置

? 与3360-Pattern匹配,但未获得匹配结果

x|y: -匹配x或匹配y

关于上述问题,将逐步尝试验证。

1 )如何只使数字一致?

与单个整数匹配的元字符可以是d,与多个整数匹配的数字字符串可以是d。 (当然,*实际上也是可能的。 很明显,元字符匹配结果是元字符*匹配结果的子集。 )如何确保整个字符串中只出现数字? 答案是用元字符^和$限制输入值

也就是说,^和d的组合告诉程序需要排除输入字符的开始位置不是数字的情况。

只有同时满足这两个限制,才会输出匹配结果。 (对于中间不是数字的情况,此表达式不会继续。 因为,当判断为不是数字时,d意味着匹配结束,然后$符号发现结束位置不是数字,匹配失败。 请取消$元字符限制,查看中间不是数字的匹配结果)。

2 )如何使只有字母一致?

结构过程是一样的。 请注意,在当前限制下,w不适合匹配w字符,因为w可以同时匹配数字和下划线。

所以我试着用[a-zA-Z]代替了这个。

3 )如何匹配数字或字母)?

将前两个步骤的结果构建为x|y格式。

4 )对于步骤3的结果,该如何优化?

需要注意的是,在步骤3中,步骤1和步骤2的结果采用了“x|y”的形式,因此使用了两个括号进行包裹,以避免这两个子表达式模糊。

所以我遇到了一个问题。 括号除了具有通俗意义上的隔离、提高优先顺序等作用外; 正则表达式还用于收集和保存括号中子表达式的匹配结果。 因此,如果不需要该子表达式的匹配结果,则为元字符“? 实现:”的想法。 当然,需要使用的时候不需要考虑吗?元字符的作用。

3.2,数字@数字.com类:

相关元字符:

d -表示[0-9]的整数数字;

w -显示字母、数字和下划线

-表示出现在符号(即符号前面的子表达式)必须至少出现一次。

-表示出现在符号前面的子表达式必须出现0次以上

? -表示出现在字符前面的子表达式出现0次或1次

^ -略

. -略

? 与3360-Pattern匹配,但未获得匹配结果

通常使用和*,以便符号前面的最后一个字符多次出现,但例如,在zo中,应用于符号的字符是o而不是zo。 因此,zo这个正则返回与zo、zoo、zo .匹配,但不与zozo匹配;

但是,在上述表达中,之所以作为面向初学者的教程中表达的“子表达式”进行说明,是因为“文字”的概念与通常意义上的c不同

har,我是可以通过小括号()去构造新的“字符”的(而常规意义下,超出一个char的字符,再表述为字符就有点歧义了,所以在初学阶段,理解为子表达式会更合适一点);这意味着,我要向匹配zozo的话,可以用正则表达式(zo)+

虽然上述想尽可能去解释清楚这个概念,但为了防止误解,或是为了加深印象,您最好可以多做尝试。

所以上述正则可以对号入座:/d+@d+.w+/

在优化上述正则前,我想就@和.这样的字符引申出一个概念:在无解的情况下,可以使用通俗语言表达形式去构造正则;

原因是如下:

1),某些符号在不具备很强复用性的情况下是没有简写形式的,这也是为什么对于[a-zA-Z0-9_]这个正则可以用 w来替代;(当然,基于下划线都被丢到w来看,哪天@符号被丢进去倒也不奇怪,毕竟字母和数字也没很强的关联不是?)

2),在精通之前,您最好做好先初步构造,再尝试优化这一流程的心理准备;比如上述正则还可以更粗糙一点: /d+@d+.com/(虽然这样一来,就屏蔽了.org,.cn这类的顶级域名)

那么对上述正则,可以如何优化呢?

1)@符号前有个d+,@符号后有个d+,那能不能将他们合在一起呢?

这种思路是可以的,主要在于@符号如何处理呢?可以考虑用元字符“?"来标识它可出现可不出现。然后为了保证合并后的子表达式出现两次,我需要将其用小括号包裹,并用+号来对他进行扩展(其实*号也可以,毕竟考虑到子表达式需要出现2次,那么>=0和>=1在这种情况下就没什么区别了);于是我得到了新的正则 /(d+@?)+.w+/

2)虽然我在优化1)处用小括号对@符号的前后进行了整合,但小括号有个特性—对括号内的子表达式进行收集和存储,于是,我得到了下边的结果:

/(d+@?)+.w+/的匹配结果

对于上述结果,您可以用(?:pattern)表达式来进行设定,它的含义是,匹配pattern部分的内容,但是,不缓存其匹配结果。基于对该元字符的应用,我得到了如下结果:

/(?:d+@?)+.w+/的匹配结果

3)对于上述正则表达式,您也许会发现,其对邮箱的起始字符未限定

ps:我当前是在基于对“数字 + @ + 数字 + .com”这一类邮箱做处理,所以按照这类邮箱的定义,是不应该出现出现非数字的情况的);所以有了如下结果:

/(?:d+@?)+.w+/的匹配结果

实际上这种已经不符合第一种邮箱格式了,为了排除这种可能,我不得不考虑在首位加个符号^以标识邮箱是以数字开始输入的:/^(?:d+@?)+.w+/

4)然后我发现,上述表达式有一个严重的bug - 对于符号“.”没有进行转义

于是出现了以下错误的(❌)匹配结果:

没有转义的元字符.引发的异常匹配-1

那么上述错误是怎么发生的呢?

您可以尝试从结果一步步逆推回去。当然,我当前也是如此做的,比方说111222335556666@这个数字部分说明第一部分的d+是生效了的,同时元字符?对其前面的子表达式(即@部分)可出现0次或1次的表述,使得结果里第一部分数字后跟着一个@;至此第一部分的数字和@符号匹配完毕;

紧接着应该匹配第二部分的数字,从结果可知,第二部分的d+匹配到了163,@没出现是因为元字符?标识它可以不出现。

那么上述异常结果中,wwww是怎么来的呢?

其原因是元字符.没有做转义,而元字符.的含义是匹配除换行符和回车符之外的任意单个字符。从结果来看,由于元字符.紧跟在匹配数字的正则子表达式之后,于是它顺利匹配到了163之后的单个字符w;而剩下的3个www则是由w+完成的匹配。

上述错误得出的教训:1,尽可能熟悉每个元字符的含义;2,该转义的字符千万别漏了。

上述错误修正后的结果:/(?:d+@?)+.w+/

上述错误的同类结果:

没有转义的元字符.引发的异常匹配-2

它出现的原因大体同上,但上述结果的出现有一个地方需要重点说明下:正则表达式默认是贪婪匹配模式,这意味着,(假如您大致懂一点回溯的内容的话),一次能到终点的操作,它绝对不会回溯一次另外选一条路走!这一点很重要!

这导致了上述表达式中(?:d+@?)+这个部分只执行了一次,得到了结果“111222335556666@”;然后紧跟其后的元字符.匹配到了w;然后由于元字符w表述了字母、数字、下划线三种概念,于是它跟元字符+一起,匹配到了最后的www163 部分。关于上述结果的验证过程,可以考虑将正则的w+部分去掉,您会发现,结果是“111222335556666@w”。

也许您可以试着分析下如下两个字符串的匹配结果:

“111222335556666wwwww@163.com”

“11122233wwww5556666@163.com”

5)然后我发现,第4步中得到的结果还有瑕疵 - w 除了字母,还能匹配数字和下划线

于是下边的错误也就发生了:

w+并不适合用来匹配纯字母组成的域名部分

为了修正错误:我将表达式调整为/(?:d+@?)+.[a-zA-Z]+/(当然,假设有人把域名写成COm这种形式,我建议还是整体对邮箱字符串做一下toUpperCase或者toLowerCase比较好!虽然是可以做进一步拆分校验,但严格来说,这并不属于校验不合法的范畴)

3.3,数字、字母 + 下划线 + @ + 数字|字母 + .com:

相关元字符:

w  -  表示字母、数字、下划线

+   -  表示该符号(即符号+)前出现的子表达式需要至少出现1次;

*   -   表示该符号前出现的子表达式需要至少出现0次

? -   表示该字符前出现的子表达式可以出现0次或1次

^   -   略

.   -    略

经过上述3.1部分的啰里吧嗦,我想初步的正则表达式并不难配,对吧。

比如:/^(?:w+@?)+.[a-zA-Z]+/

接着,请跟我一起来拆解下上述的表达式:

1)^(?:w+@?)+:表述了我想匹配以w开头,且形如:zhangsan_1@163(qq)这样格式的字符串

2).:表述匹配普通字符.

3)[a-zA-Z]+: 最后一部分w+表述我想匹配最后的域名部分(当然,形如.com.cn暂时不在讨论范围内)

通过拆解表达式,您可以发现,上述部分出现了3.2中第5步的错误,即w并不光匹配字母、数字,还匹配下划线。

而下划线出现在第一部分,即@符号之前,可以说是符合本回合邮箱构造规则;但是,若出现在@符合之后的第二部分,那就大为不妥了,而上述表达式显然,会出现以下匹配结果:

/^(?:w+@?)+.w+/表达式的异常匹配-1

/^(?:w+@?)+.w+/表达式的异常匹配-2

由于上述的表达式对于第二部分内容(@字符之后,.字符之前),匹配的并不尽如人意。所以子表达式“^(?:w+@?)+”需要对第二部分的匹配进行优化。

既然问题出在第二部分,那么意味着,我在3.2中分析时,对@符号前后子表达式的整合(即将xx@xx整合为(xx@?)+这种形式)就不攻自破了。

那么,对于第二部分的匹配期望,我现在需要构造一个正则表达式,使得能且仅能匹配(纯数字或纯字母表达式的)其中一种情况,即要么匹配类似ww这样的字符串,要么匹配111这样的字符串,其他字符串暂且假定非法。

于是,您会发现,我在3.1中已经引导您做过类似的校验。然后,您可能会犯我之前犯过的错误,即简单粗暴地将其添加到正则表达式中,形成这样的式子:/^w+@(?:^d+$|^[a-zA-Z]+$).[a-zA-Z]+/;

然后您会发现,这下不仅仅是错误的字符串无法通过校验,正确的字符串也不行了!

于是,我希望您能跟我一起来重温一下元字符^和元字符$的概念:前者匹配输入的起始位置,后者匹配输入的结束位置;所以,这就是我在3.1中加入起始和结束元字符可以生效,而在3.3中失效的原因(因为对于输入者而言,可以人为的理解某一段输入值的开始和结束位置,但对于程序而言,字符串的起始和结束位置是相对于整体而言的,而非局部的某个子串。)

基于上述反思,较为合理的一个正则表达式为:/^w+@(?:d+|[a-zA-Z]+).[a-zA-Z]+/

3.4,待续......

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。