zoukankan      html  css  js  c++  java
  • js 正则 exec() 和 match() 数据抽取

    js 的正则表达式平常用的不多,但以前抽取数据的时候用到过,主要是有这样的需求;

    var text='<td class="data">2014-4-4</td><br /><td class="data">2014-4-5</td>';
    //希望输出 ["2014-4-4", "2014-4-5"]

    难倒不难,如何比较好的实现是个问题;

    如果要提取其中的数据,主要就是 String 对象的 match()、replace()、split() 方法或者 RegExp 对象的 exec(),但是应用的时候,还是有点坑的;

    首先写出正则,这个不难,一个非全局,一个全局:

    var re = /<td[^>]*?>([sS]*?)</td>/,
        reg = /<td[^>]*?>([sS]*?)</td>/g;

    但是匹配多个 <td></td> 的时候,match 方法有点特殊:

    image

    match 的特殊在于:

    非全局正则,可以返回捕获组,也就是正则里面()里面的内容,但不能多次匹配;

    全局正则,可以多次匹配,但不返回捕获组;

    实际上,如果全局正则,多次匹配还返回捕获组的话,返回的数据就不可能是个简单数组了,因为 n 次匹配,m 个捕获组,那返回的结果就是,数组里有 n 个匹配结果,每个匹配结果里,还要放一个数组,用来表示每个捕获组的值;

    如果换成 exec(),结果如下:

    image

    exec() 特殊在于:

    不管正则是否加全局,返回的内容是一样的

    具体实现:

    1、这里,我们先用 match 实现一遍,按照前面的思路,就是用全局正则 match 一下,然后再遍历获取到的数组,通过非全局正则捕获我们要的东西:

    text.match(reg).map(function(v) {
        return v.match(re)[1];
    });
    //返回 ["2014-4-4", "2014-4-5"]

    比较好理解,但是需要两个正则,一个全局,一个非全局;

    2、如果用 exec(),

    var temp = [],data = [];
    while ((temp = reg.exec(text)) !== null) {
        data.push(temp[1]);
    }
    //data:["2014-4-4", "2014-4-5"]

    这样写的原因是,RegExp 对象的方法,经常有 lastIndex 的属性,exec() 在执行的时候,实际上每回只匹配一次,然后改了 lastIndex 属性的值为下一个开始的地方,然后下次从新的地方开始再匹配,如果匹配到末尾匹配不到了,返回 null ,举个例子:

    image

    这个特性不注意会被坑的,比如:

    var reg=/ja/g,text='ja';
    reg.test(text); //true reg.lastIndex 返回 2,其实也就是匹配到末尾了
    reg.test(text); //false reg.lastIndex 返回 0,匹配到末尾没匹配到,返回 null,lastIndex 重置为 0;

    参考资料:

    JavaScript权威指南-第6版

    JavaScript高级程序设计-第3版

  • 相关阅读:
    Delphi TStringList的用法
    Android Studio使用教程(一)
    如何在win7下安装和配置Android Studio
    python基础字符串单引号双引号和三引号
    同步和互斥
    posix多线程有感线程高级编程(条件变量)
    VMware网络配置详解
    posix多线程有感POSIX 线程间的内存可视性
    进程及相关API
    POSIX线程属性
  • 原文地址:https://www.cnblogs.com/xianshenglu/p/8118626.html
Copyright © 2011-2022 走看看