正则表达小结与小知识点集锦

前端之家收集整理的这篇文章主要介绍了正则表达小结与小知识点集锦前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

背景介绍

这几天,刚来公司,导师安排点任务增加功能,以便熟悉了开发环境。接到的任务中,有一个环节需要处理一个业务的json数据,具有多级嵌套,我要做的是让使用者可以修改其中的"userName"。

有两个思路

  • 利用正则表达式进行匹配替代

  • 利用遍历修改键值

当然,看到两个思路的高下,在大部分情况下都是可以直接得出结论的,正则肯定是优于遍历的。

正则表达式小结

创建方式

  • 直接量语法
    /pattern/attributes

  • 创建RegEx对象的语法
    new RegExp(pattern,attributes)

语法属性说明:pattern我们写的正则表达式的规则,而attributes则是规则的修饰符,g为全局匹配,i为区分大小写的匹配,m为多行匹配。

语法

括号

用于查找某个范围内的字符

[acg] //匹配acg任一项即可
  [^acg]//匹配acg之外的任何一个字符
  [a-z] //匹配a到z  26个小写字母的任何一个即可
  [A-Z] //匹配A到Z 26个大写字母的任何一个即可
  (red|blue|green) //匹配red或者blue或者green任何一个即可

元字符

拥有特殊含义的字符

.    //查找单个字符,除了换行以及行结束符
\w   //查找单词字符
\W   //查找非单词字符
\d   //查找数字
\D   //查找非数字
\xxx //查找八进制书xxx规定的字符

量词

描述规则执行的次数要求以及位置要求

n+ //匹配任何包含至少一个n的字符串
n? //匹配任何包含零个或者一个n的字符串
n* //匹配包含任一个n的字符串
n{x,y}  //匹配包含x到y次n的字符串
^n  //匹配开头含有n的字符串
n$  //匹配结尾有n的字符串
?=n //匹配任何其后紧跟指定字符串n的字符串
?!n //匹配任何其后没有紧跟字符串n的字符串
\b  //匹配一个字边界,即字与空格间的位置
\B  //非字边界匹配

方法

RegExp的方法

  • compile 编译正则表达式

  • exec 执行正则表达式,并返回找到的值与位置

  • test 检测是否真的含有符合正则表达式的字符串,返回布尔值

String对象的方法

  • search 检索与正则表达式相匹配的值

  • match 找到一个或者多个正则表达式的匹配

  • replace 替换与正则表达式相匹配的子串

  • split 把字符串分割为字符串数组


小知识点集锦

子表达式

一个正则表达式可分为许多子表达式
例子:利用子表达式可以将通用资源指示符 (URI) 分解为其组件。假定您想将下面的 URI 分解为协议(ftp、http 等等)、域地址和页/路径

var test = http://www.w3cschool.cc:80/html/html-tutorial.html;

/\w+:\/\/[^/:]+:\d*?[^# ]*/.exec(test)  
     //只可以匹配到链接
//输出结果
["http://www.w3cschool.cc:80/html/html-tutorial.html",index: 0,input: "http://www.w3cschool.cc:80/html/html-tutorial.html"]      

/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/.exec(test)  
    //不仅可以匹配到链接,还可以把链接分为各个部分输出
//输出结果
["http://www.w3cschool.cc:80/html/html-tutorial.html","http","www.w3cschool.cc",":80","/html/html-tutorial.html",input: "http://www.w3cschool.cc:80/html/html-tutorial.html"]

贪婪的量词

? * + 三者都是贪婪的

因为他们会尽可能多的匹配字符串,只要在他们后面再加一个?就可以实现非贪婪或者最小匹配
实例如下

<h1>Hello world!<h1>
//下面的表达式匹配从 < 到关闭h1标记的 >之间的所有内容
/<.*>/
//如果你只需要匹配开始的h1标记,下面的非贪婪表达式只匹配<h1>
/<.*?>/

圆括号的副作用消除

圆括号有一个副作用,那就是相关匹配会被缓存,此时可在在圆括号中加上?:在写正则表达式

/(?:<.*>)/

String.match(/<.+>/g) 与 RegExp.exec(string)的区别

不得不说这个是让我迷惑的很久的坑

  • String.match(/<.+>/g)
    这个是字符串方法,返回数组,包括与正则表达式匹配的第一个或者所有字符串,是否返回多个值由修饰符g决定(不返回子表达式的匹配结果)

  • RegExp.exec(string)
    这个是正则表达式对象的特有方法,返回一个数组。数组包含:正则表达式匹配到的第一个字符串,各个子字符串匹配到的字符串,另外还有两个键值index与input,分别输出匹配到的字符串的第一个字符的位置与被检测的字符串。

所以想要输出()的子字符串匹配的字符串必须要用exec,(?:)同样也只要在用exec的时候才能检测到效果

RegExp.exec(string) 总结

介绍

这个可以取到各个子表示的结果,并且可以返回对应的index值。拥有非常大的想象空间。比如我想获
"userName":"test"的值使用match,我们需要先匹配整个键值对,再对这个键值对进行处理才能取到键值。而使用exec,通过子表达式,我们则直接可以获取到键值。

当然,exec有个蛋疼的地方是只能取到第一个匹配的字符串,也就是说修饰符g设置没设置对他来说都一样。

那我们如何用exec来全局匹配呢?

首先,我们来了解一下exec的一个特殊地方

当exec执行全局匹配模式时,exec的行为就略有变化。这时它会定义lastIndex属性,以指定下一次执行匹配时开始检索字符串的位置。在找到了与表达式相匹配的文本之后,exec方法将把正则表达式的lastIndex属性设置为下一次匹配执行的第一个字符的位置。也就是说,可以通过反复地调用exec方法来遍历字符串中的所有匹配文本。当exec再也找不到匹配的文本时,将返回null,并且把属性lastIndex重置为0。

var s = "Hello world Hello world";  // 测试使用的字符串直接量

var r = /Hello/g;    // 匹配模式 一定要加上修饰符g

while((a = r.exec(s)) != null){ // 循环执行匹配操作

  console.log(a);
  console.log(r.lastIndex);
  /* 显示每次匹配操作时返回的结果数组信息*/
}

测试结果

["Hello",input: "Hello world Hello world Hello world"]
5
["Hello",index: 12,input: "Hello world Hello world Hello world"]
17

bingo,完成全局匹配。注意正则表达式,一定要加上修饰符g。要不然lastindex并不会改变,
循环会始终为真,不断执行。

结语

这篇小结,也是花了好几个小时去查资料,测试最后写出来的,之前也看过许多正则的资料,却始终停留在看看,认为知道了,每次想起来的时候,又都忘了,前几天,用的时候就手忙脚乱的边查资料边coding。终于认识到了自己的学习方式给自己带来的深刻问题。

其实,走上技术的路,时间也不短了。
但确实在技术学习的路上,有许多观点,随着时间与自身情况的变化,并未及时的更新。

曾经,在决定未来走向的时候,为了海量的获取信息来看到更远的未来,从而找寻一条能够坚定走下路。读书与阅读的时候,采用快速阅读的方式,不去细细咀嚼,只觉得看过一遍,迅速了解扩展视野,了解更多的东西就好。开始的时候,这种方式为我建立了认知,获得了远大于自身水平的视野。但是视野不曾有技术的支撑,只是一幢危楼而已。行之今日,这种学习方式暴露的问题,越来越大。后来,虽有意识,却不曾有动力予以改正。

幸得近来被人指正,得以真正意识到问题的严重性。

非自己所研究的方向,有一定认识就好,用不着过度深入,采用快速阅读的方式,自然是极好的。能够快速建立认识。但是真正自己的研究方向,发散性阅读才是更好的方式,对于每个点,都不仅仅局限于理解这一个点,能够另行查阅许多相关的资料,这样的方式,看一本书读懂一本书,并扩展阅读了许多相关的资料。这确实是更为行之有效的技术学习方式。而不像之前的方式,看似读过,却处处有漏洞,不曾真正的读透一本书,希望临到项目,临到业务。再去真正实践,去真正的掌握。是一种极为不靠谱的方式。

学习的方法的重要性,不亚于学习本身,也是值得我们去反思并改进的。

参考资料

正则表达式|菜鸟教程
W3Cschool正则表达式
使用exec增强正则表达式功能

WilsonLiu's blog首发地址:http://blog.wilsonliu.cn

猜你在找的正则表达式相关文章