假如正则从来没来过,我们该如何去匹配一个字符串?
正则表达式其实挺难的,对于新手来说就好比一本天书。很多高端大气上档次的教程啊教材啊博客啊一般都是先列出框框条条,再来细讲,先元字符再量词再分组再反向引用。我估计是国人都受到了国外教材的影响,因为这些东西是他们整出来的。对于他们来说思路是很清晰的。老手还好,勉强能吃透。新手你没个几十遍的功夫,门都找不到在哪里。光那些规则,字母意思啊就够你喝一壶的了,你是忘了看,看了忘。(ps:本文针对javascript正则)
假如我们根本就不知道有正则这玩意儿存在,要去匹配一个字母串我们应该怎么做了?让我们也做一回创造者吧
当你输入你的用户名和密码的时候,服务器君为了给自己少点麻烦,就给浏览器君打了个电话说:你定的货的参数可要对着了,哥的时间很宝贵。浏览器君坐不住了,立马找来自己的小弟,权叫他正则君吧。你把这事给我办一下,正则君可是倍感压力啊,可是他也坚信世界上没有过不去的坎,这不就是要我搞一些规则来检查我输入的字符串符不符合要求啊,就这样正则君开始了它漫长而又艰辛的思考之路
谁都不是傻蛋,都知道字符串一般都是有字母数字下划线什么的组成,变量命名不是都喜欢这么整嘛。先入为主,首先来检测一个字母吧。26个英文字母不就是a-z,正则君不是牛顿君,当然也不能笨到用a来匹配a,b来匹配b....,那这种匹配就没有意义了吧,毕竟你的输入是千变万化的。需要的是以一敌十,以点破面。
a或b或c...或z来匹配一个字母。若a没匹配上就b上,b不行再c上···,一直下去,只要某个字母匹配上,就大功告成了。当然为了减少书写量,正则君把字母这一类整合了下,都是一路货(或)色,就用个大家最常见的[]吧,范围很明显用-,就成了这样[a-z]。长舒一口气了,我们总的试试我的思路对不对啊 ,整个test函数吧,其实就是简单的if-else。
1 var reg=/[a-z]/; 2 var result=reg.test("d"); 3 alert(result);//true
就这样一个字母搞定了,不对啊,字母不是还可以大写吗,这个简单,换成[A-Z]不就ok了。匹配字母简单的综合就是a-z或A-Z,放一块儿就是[a-zA-Z]。也就是你这个字母可以是a或者b....或者A或者B...,一路或者。
1 var reg=/[a-zA-Z]/; 2 var result=reg.test("A"); 3 alert(result);//true
一个字母搞定了,该数字了吧。那要是一串字母咋办,还是先把数字匹配了再说吧,0-9就是我们的数字吧,还是一路或下去吧(谁叫它是杰伦迷),0不行1上,1不行2上···只要某一个数字匹配上,就表示输入合理。把上面字母类格式搬下来[0-9],试试效果:
1 var reg=/[0-9]/; 2 var result=reg.test("3"); 3 alert(result);//true
这一不小心又弹出了true,正则君这心里开心的啊,先去喝个小酒整个小菜吧
酒足饭饱了,要是一串字母咋办,一溜数字咋办(本山大爷语录,这可咋办啊),前面不是说只要匹配成功一个就终止了,后面的咋办了?多个字母不就是一个字母的不断计数嘛,有几个王八我抓几个王八。正则君大手一挥,在后面加个计数器吧,就用{n}吧。[a-zA-Z]{3}。(ps:括号用的只剩下()了。就留着它干一番大事业吧。)
1 var reg=/[a-zA-Z]{3}/; 2 var result=reg.test("adc"); 3 alert(result);//true
1 var reg=/[a-zA-Z]{5}/; 2 var result=reg.test("adCef"); 3 alert(result);//true
同样的,一串数字[0-9]{3}
1 var reg=/[0-9]{3}/; 2 var result=reg.test("123"); 3 alert(result);//true
要是这个串中有字母有数字咋整,这不就是或小写字母或大写字母或数字吗?看[a-zA-Z0-9]表现如何
1 var reg=/[a-zA-Z0-9]{3}/; 2 var result=reg.test("a2z"); 3 alert(result);//true
一日浏览器君大闹,我要的不是字母不是数字。正则君灵机一动[^a-zA-Z]匹配非字母。[^0-9]匹配非数字,自然[^a-zA-Z0-9]匹配非字母数字了.要要,切克闹,字母数字都不要(煎饼果子来一套)。
当然我们肯定无法限定你输入字符串的长度了。所谓沙场上敌将数人,各怀绝技。QQ君勒马上前,我可是有5位元老Q,还有12位的菜鸟Q。正则君呷了一口小酒喝道{5,12}通杀。银行小职员轻声道,金库的银子可不好数啊,+ 再杀,{n,}还杀。赌场君冷笑道你这是押大还是押小,?走起。刹那间,正则是见招拆招。大战多雄未卖一个破绽。后人将这些招式记载如下:
? | 出现零次或一次 |
* | 出现零次或多次(任意次) |
+ | 出现一次或多次(至道一次) |
{n} | 对应零次或者n次 |
{n,m} | 至少出现n次但不超过m次 |
{n,} | 至少出现n次(+的升级版) |
正则君在不断的迎敌过程中,也对自己的武功招式也做了一些总结,用本门心法收录如下:
. | [^\n\r] | 除了换行和回车之外的任意字符 |
\d | [0-9] | 数字字符 |
\D | [^0-9] | 非数字字符 |
\s | [ \t\n\x0B\f\r] | 空白字符 |
\S | [^ \t\n\x0B\f\r] | 非空白字符 |
\w | [a-zA-Z_0-9] | 单词字符(所有的字母) |
\W | [^a-zA-Z_0-9] | 非单词字符 |
一个字母(数字)搞定了,一串字母(数字)也搞定了。自此之后正则君以为江湖再无大事,从此高挂免战牌。
不巧江湖最近出现了一个url地址君“http://www.ora.com:80/goodParts?fragment”,连破数名正则小弟。数日鏖战,正则君也败下阵来,从此闭门苦研。誓斩地址君于马下。里面字母数字冒号?号,队伍很庞大,招式很诡异。这么多,我们只有分散围之,各个击破,来他个围点打援战术如何。怎么分隔,不是还有()没用上嘛?
- 细看地址君头带协议"http"帽,也就是多个字母外加一个:。由于考虑到协议可能会变身https之类的,看来要用上本门心法匹配至少一个(+)字母了:([A-Za-z]+):
- //两条斜杠与后面的域名隔开(\/{2}).这时候正则君突然想起来自己还缺少一套霸气的铠甲。就去买了一套/***/雁翎甲。这个时候/可能会是正则君的铠甲后背上千年玄铁冲突,得特殊标记(\)转义一下。(\/{2})
- 域名就是由一些数字字母和.等组成的[A-Za-z0-9.]
- 端口肯定是:后面加数字了:(\d+)
- 一般问号前后的东西就是执行的查询和对应的参数,有必要用?把剩下的杂牌军分成两组。前面一组只要没出现?就可以。当然这个查询时可有可无的,用本门心法*来搞定它也就是前面说的不要问号/\([^?]*)。
- 接下来的一组自然是?加参数了,参数随意,就用无敌杀招.吧?(.*)
好了综合一下试试看看能不能破了地址君:
1 var reg=/([A-Za-z]+:)(\/{2})([A-Za-z0-9\.]+)(:[\d+])(\/[^?]*)?(.*)/; 2 var result=reg.test("http://www.ora.com:80/goodParts?fragment"); 3 alert(result);//true
现在我们要秋后算账了,屈服于地址君淫威的某些正则君小弟被抓出来批斗了。我们需要把每一组匹配的东西单独拿出来用啊,如果我们想要把域名小弟揪出来。$3小手这么一抖,看下面:
1 var reg=/([A-Za-z]+:)(\/{2})([A-Za-z0-9\.]+)(:[\d+])(\/[^?]*)?(.*)/; 2 var result=reg.test("http://www.ora.com:80/goodParts?fragment"); 3 alert(RegExp.$3);//www.ora.com
当然正则君也不是绝情之人,有些背叛自己的小弟是被逼无奈的就既往不咎了,我们可以把他们放在非捕获性分组里,给他的标号?:。我只看你们一眼,就不记在顺天衙门的小册子上了。看下面我们放端口一马吧,知道你是被逼无奈。
1 var reg=/([A-Za-z]+:)(?:\/{2})([A-Za-z0-9\.]+)(:[\d+])(\/[^?]*)?(.*)/; 2 var result=reg.test("http://www.ora.com:80/goodParts?fragment"); 3 alert(RegExp.$2);//www.ora.com
域名小弟这个倒霉玩意儿,怎么又是你啊。看来分组小本上确实没了端口君哟(非捕获性分组不存放在匹配结果中,没有组号)
此役之后,正则君在江湖上名声大噪。江湖人称正则表达式。他也不断研习,一日看见了巴蛇吞象这个故事,灵感突发。正则君吞字符串,我现在牛了,我一口气先吞下你,要是不是我要的那部分,就一节一节往外吐,此招式为贪婪匹配。面条一口一口吃,吃饱就好,就是非贪婪匹配?。。。。。江湖路依旧,淡看功与名。
小可不才,此文极度不严谨,为初学者引路而已。此文原创,转载请注明出处。如果你觉得文章还不错,就推荐一下下吧!!!!
更多详情参见此文:http://www.cnblogs.com/rubylouvre/archive/2010/03/09/1681222.html
http://www.cnblogs.com/dwlsxj/p/3532458.html