正则

作者: xiao_A | 来源:发表于2016-02-20 22:33 被阅读175次

    一直使用正则但是一直没有能够把正则的基本书完整的看完,所以边学边看吧。当然对于这些技术,最好还是能够有一个非常系统完整的学习。争取后面能把《正则指引》看完。
    说明:本文任何函数解释和分析都以W3C JS Reg文档解释为准,本人技术粗浅,有可能有理解不到位的地方,文章当日后发现理解错误会持续更新)

    正则基础参考文档

    非常推荐这一篇网上最好的正则快速入门教程+手册,30分钟正则系列
    此外,遇到具体的问题和一些方法函数请参考W3C JS Reg文档

    JS正则基础

    JS正则定义

    本文的RegExp采用直接量语法表示:/pattern/attributes。attributes有三个选择,i、m和g,m(多行匹配)不常用直接省略,所以一个pattern(匹配模式)可以表示如下:

    var pattern = /hello/ig;
    i(ignore)表示不区分大小写(地搜索匹配),比较简单,以下例子中不加述说;g(global)表示全局(搜索匹配),即找到一个后继续找下去,相对复杂,以下各种方法中会特别介绍。

    还有一种是使用

    var re = new RegExp();//RegExp是一个对象,和Aarray一样
    
    //但这样没有任何效果,需要将正则表达式的内容作为字符串传递进去
    
    re =new RegExp("a");//最简单的正则表达式,将匹配字母a
    re=new RegExp("a","i");//第二个参数,表示匹配时不分大小写
    

    ** 注意 ** : 使用RegExp类的方式创建的正则对象中需要双重转义,如正则中输入'',本身必须转义为'\',但是在这个对象中创建字符串必须为'\\','\'为转义的最终出现在正则中的'',总之很麻烦,而且定义的写法也很啰嗦,所以直接用所谓的量语法来定义就好/(your reg)/写起来真的很简单,随写随用就好啊。

    JS正则RegExp对象

    RegExp 对象方法
    • test -- RegExp的test方法用来测试字符串是否匹配给出的匹配模式,返回布尔值,检测指定字符串是否含有某个子串(或者匹配模式),返回true或者false。
    • exec -- RegExp的exec方法返回包含第一个匹配的的数组或null
    • compile,把正则表达式编译为内部格式,从而执行得更快(我没怎么用过,具体需要再研究下这个优化的效果),但是可以想象,在复杂多次正则匹配的情况下,这应该是一个优化的好路子
    RegExp 对象属性
    • global -- 布尔值,若全局选项g已设置则返回true,否则返回false;(即/g)
    • ignoreCase -- 布尔值,若忽略大小写选项i已设置则返回true,否则返回false;(即/i)
    • lastIndex -- 整数,使用exec或test方法时被填入,表示下次匹配将会从哪个字符位置开始(根据说明,应该是只有在使用g全局正则的时候这个值才会被修改,否则应该永远是第一个位置才对,* 没有代码实践过,有待进一步研究 *)
    • multiline -- 布尔值,表示多行模式选项m是否设置,若设置则返回true,否则返回false(即/m,* 多行模式需要进一步研究用法 *)
    • source -- 正则表达式的元字符串形式。/\/的source将返回'\'。

    JS正则String对象

    由于正则天生的好基友就是String,所以必须有通过string来搞正则的路子

    String 对象方法
    • search -- 检索与正则表达式相匹配的值。搜索指定字符串中是否含有某子串(或者匹配模式),如有,返回子串在原串中的初始位置,如没有,返回-1。
    • match -- 找到一个或多个正则表达式的匹配。
    • replace -- 替换与正则表达式匹配的子串。用另一个子串替换指定字符串中的某子串(或者匹配模式),返回替换后的新的字符串 str.replace(‘搜索模式’,'替换的内容’) 如果用的是pattern并且带g,则全部替换;否则替换第一处。

    如果需要替代的内容不是指定的字符串,而是跟匹配模式或者原字符串有关,那么就要用到$了(** 记住这些和$符号有关的东东只和replace有关哦 **)。

    • $1、$2、...、$99 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
    • $& 与 regexp 相匹配的子串。
    • $` 位于匹配子串左侧的文本。
    • $' 位于匹配子串右侧的文本。
    • $$ 直接量符号。

    Sample Code

         name = "Doe, John";
         name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1");
    
    • split -- 把字符串分割为字符串数组。

    那么问题来了

    RegExp和String都好用,那么我应该用谁呢?谁更好?又有什么区别么?

    关于使用情景
    1. 由于RegExp自带compile方法,那么很明显需要** 优化性能 **那么你最好的选择必然是RegExp
    2. 其他的,反正由于无论用哪个传入的都是RegExp对象,那么没有必然的谁更好,一定要用谁,那么怎么用就取决于这些方法的区别
    <a href="#diff">String和RegExp比较</a>
    • 关于test和search:search不仅能反馈是否匹配上,而且能够返回位置,test只能返回是否匹配上
    • 关于exec和match:这两个比较复杂点,坑比较深,** 非常重要!!! **

    match是exec的轻量版,当不使用全局模式匹配时,match和exec返回结果一致;当使用全局模式匹配时,match直接返回一个字符串数组,获得的信息远没有exec多,但是使用方式简单。

    以上引用自我所认识的JavaScript正则表达式文章
    好那么我们继续延生我们的思考,并进行一些实验,比较这两个函数是最实用也是用的最多的解决最多问题的

    "abc1 bcd2 cde3".match(/(\w+)(\d+)/)
    

    result:

    result = ["abc1", "abc", "1"]

    分析,这里result[0]表示的是match的匹配的string
    result[1]表示的是match中regexp的第一个分组匹配结果
    result[2]表示的是match的第二个分组匹配的结果

    /(\w+)(\d+)/.exec("abc1 bcd2 cde3")
    

    result:

    result =  ["abc1", "abc", "1"]
    

    看来果然和match是一样的
    Go On!

    "abc1 bcd2 cde3".match(/(\w+)(\d+)/g)
    

    result:

    result = ["abc1", "bcd2", "cde3"]
    

    加了g之后的match的结果数组已经不包括了分组的相关信息了,每一个结果中的元素都是匹配的string

    Paste_Image.png

    将此结果和下面的exec做对比

    /(\w+)(\d+)/g.exec("abc1 bcd2 cde3")
    

    result:

    result = ["abc1", "abc", "1"]
    

    加了g之后的exec还是无动于衷,还是和之前一样,只是匹配并返回了第一个string,但是仍然包含了所有的分组的匹配
    然后根据一些资料,在g下,exec会修改上文所述的RegExp的lastIndex值,从而当下一次exec执行时,会接着上一次的lastIndex来继续匹配.但是本例中所使用的是/(\w+)(\d+)/g 常量,所以对象lastIndex的值永远都是0

    Paste_Image.png

    这里demo了使用pattern变量的方式,其中index 和input是这个array的属性

    总结:如果你只是需要获取所有匹配的string那么match是最好的选择,如果你有更高更复杂的需求,使用exec,并且使用g来不断执行exec获取每一个匹配string和该次匹配的分组的匹配结果才是最强大和完美的用法

    参考文献
    30分钟正则系列
    W3C JS Reg文档
    我所认识的JavaScript正则表达式

    相关文章

      网友评论

          本文标题:正则

          本文链接:https://www.haomeiwen.com/subject/uuvvkttx.html