JavaScript中exec()方法详解

前言:

有时候学习进度缓慢,像一只慢爬的蜗牛,欣慰的是总归每天在进步,希望一切越来越好。

最近学习正则,发现javascript中exec()方法理解有些不容易,因此稍加整理了一下,一做分享二也希望大神看到不到之处多多指点。

另本文只讲解exec()方法,至于正则语法及在js中使用请自行谷歌。

一、RegExp对象的声明及exec()方法的使用

声明一个RegExp有两种方式:
1)var re=new RegExp(pattern,modifiers);
2)var re =/pattern/modifiers;

注释:
pattern(模式): 描述了表达式的模式
modifiers(修饰符) 用于指定全局匹配、区分大小写的匹配和多行匹配,具体有 i 、g 和 m 三类,这三类也可以自由组合也可以不添加修饰符。

修饰符 释义
i 代表忽略大小写
g 代表全局匹配
m 执行多行匹配
示例:

1)var re=new RegExp(pattern,modifiers);

var re1=new RegExp("\\w{2}");   
var re2=new RegExp("\\w{2}","i"); 
 
2)var re =/pattern/modifiers;
var re3=/\w{2}/;
var re4=/\w{2}/ig;

使用RegExp对象的exec()方法:

直接调用即可。如果匹配到字符串返回一个数组;如果没有匹配到返回null
1) var re1=new RegExp("\w{2}");

 var res1=re1.exec("要检索的字符串");

2)var re3=/\w{2}/;

var res2=re3.exec("要检索的字符串");
示例:
<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        var re1=/\d[a-zA-Z]/;   //匹配两位一个数字和一个忽略大小写的字母
        var res1=re1.exec('aa2edj3djie7788');
        var res2=re1.exec('458949468974484');
    </script>
</body>
</html>

我们断点来看var res1=re1.exec('aa2edj3djie7788');执行结果


匹配字符串'aa2edj3djie7788'结果断点.png

我们再断点看var res2=re1.exec('458949468974484');执行结果


匹配字符串'458949468974484'结果断点.png

总上所知,我们使用exec()方法得到的结果有两个,一个是存有匹配字符串的数组,一个是null

二、RegExp对象和执行exec()得到的结果分析

咳咳,这里需要划下重点。希望能仔细看下这里。
1)首先RegExp对象
只需要关系此对象的一个属性,lastIndex ,这个属性的值代表了 检索字符串 开始匹配的起始索引,依旧上代码和断点

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        var re1=/\d[a-zA-Z]/;   //匹配两位一个数字和一个忽略大小写的字母
        var res1=re1.exec('aa2edj3djie7788');
    </script>
</body>
</html>

我们来看断点中的RegExp对象,在调用exec()方法前


调用exec()方法前RegEpx对象.png

我们看调用exec()方法后的断点

调用exec()方法后RegEpx对象.png

注意,这里在调用exec()方法前后,lastIndex值虽然没有改变,但是这个属性至关重要。
1)lastIndex代表了每次匹配要检索的字符串的开始匹配的起始索引位置
2)在 修饰符使用了 g 后,此属性是变的,因此对后面理解 g修饰符是非常关键的。

2)执行exec()的到的结果
这里我们只断点查看数组结果,null也没啥好看的好像。
下面看断点截图


执行exec()返回的数组.png

来看下数组对象每个属性:
var a=res1[0]; // 匹配到的字符串
var index=res1.index; //匹配到的字符串的第一个字符 在被检索字符串String中的位置
var input=res1.input; //被检索的字符串 string
var length=res1.length; //数组的长度

三、修饰符 i 的使用

修饰符 i 代表了匹配时忽略大小写,下面上代码吧。

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        var re1=new RegExp("\\d[a-z]");   //匹配两位一个数字和一个忽略大小写的字母
        var re2=new RegExp("\\d[a-z]","i");
        var res1=re1.exec('8AJDJDJ');
        var res2=re2.exec('8AJDJDJ');
    </script>
</body>
</html>

断点查看 var res1=re1.exec('8AJDJDJ'); 执行结果


没有使用修饰符i结果.png

断点查看 var res2=re2.exec('8AJDJDJ'); 执行结果


使用修饰符i执行结果.png

四、修饰符 g 的使用

修饰符g代表全局匹配,全局匹配就是对把整个要检索的字符串全部 匹配一遍。

原理就是 当使用了 g 修饰符,每次调用 exec()方法后,如果匹配到了字符串,则 lastIndex属性的值会改变。
而没有使用 g 修饰符,每次调用exec()方法后,lastIndex值永远都为0 ,所以每次调用exec()最多只会检索出一个相同的字符。
至于使用了g修饰符,找到匹配的字符串后,lastIndex的值会被重置为匹配内容的下一个字符在 需要检索字符串 中的位置索引。

下面来上代码和断点吧,一目了然。我们一行行断点来搞清楚 g 的原理。

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        
         // 使用 g 修饰符  全局搜索
         var test1=new RegExp("\\d\\w","g");
         var res1=test1.exec("1a2b3c4d5e");
         
         var res2=test1.exec("1a2b3c4d5e");

         //综上可知, 使用g全局搜索的时候,我们可以使用循环
         do{
            var res=test1.exec("1a2b3c4d5e");
            if(res!=null){
                console.log(res[0]);
            }
            
         }while(res!=null);
        

        //没有使用 g
        var test2=/\d{2}/;
         
        var result=test2.exec("22dhdhj33djdj44");

        var result1=test2.exec("22dhdhj33djdj44");
    </script>
</body>
</html>

断点查看 var test1=new RegExp("\d\w","g");

声明使用全局搜索RegExp对象.png

断点查看 执行一次后RegExp对象 var res1=test1.exec("1a2b3c4d5e");


执行第一次exec()方法后断点截图.png

再执行一次,查看断点 var res2=test1.exec("1a2b3c4d5e");


执行第二次exec()方法后断点截图.png

综上可知,在使用g全局搜索时,可以根据 lastIndex对整个 要检索字符串进行匹配。因此,我们可以使用循环来得到 要检索字符串中所有匹配的结果。

 do{
      var res=test1.exec("1a2b3c4d5e");
      if(res!=null){
         console.log(res[0]);
      }
            
}while(res!=null);

我们来看结果吧,因为我们已经执行了两次,所以 lastIndex此时,已经为4,因此循环检索匹配从 要检索字符串的索引4开始。


巡检检索得到的结果.png

下面,我们来重点看执行到 结果为res[0]= 5e 时的断点


此时结果为5e.png

我们来看这时候的RegExp对象
这时候可以看到lastIndex值为10,即下次匹配从索引10开始,我们知道要检索的字符串
“1a2b3c4d5e”的长度为10,因此下一次调用结果为null。


结果为5e时RegExp对象.png

我们来看下一步,当结果为null时,断点截图

image.png

我们注意到,这时候,RegExp对象的属性 lastIndex的值重置为0。即下一次再调用 exec()方法,会从 要检索字符串的 0索引位置 开始匹配

通过上述一步步断点,相信你已经明白了全局搜索 g修饰符的使用原理。那么我们再来看,没有设置 g的时候,代码的断点

看这一步,var test2=/\d{2}/; 断点。刚开始 test2的lastIndex值为0


刚开始 test2的lastIndex值为0.png

执行一次,var result=test2.exec("22dhdhj33djdj44"); 得到的结果为 22

执行一次非全局搜索exec()方法.png

重点看此时的 test2属性 lastIndex的值,发现lastIndex值还是0


非全局搜索RegExp对象.png

因为当非全局搜索的时候,test2不管调用几次exec()方法 ,其属性lastIndex值都为0。
所以,非全局搜索,每次调用exec()方法总是得到第一个相同的结果。

五、修饰符 m 的使用

修饰符m执行多行匹配。代表多行模式multiline。

使用m时需要注意:
1)当要检索的字符串为单行时,使用 m无意义。很明显啊,只有一行字符串使用啥 m 啊。
2)当要检索的字符串有换行符 \n 或 \r\n时,这里要看正则表达式有没有位置符号 ^ 和 $:

①当正则表达式中存在 ^和$符号时,使用了 m ,则:
“^”与字符串开始位置以及“\n”或“\r”之后的位置相匹配,
“$”与字符串结束位置以及“\n”或“\r”之前的位置相匹配。

②当正则表达式中存在 ^和$符号时,没有使用了 m ,则:
“^”与字符串的开始位置相匹配,
“$”与字符串的结束位置相匹配。

③当正则表达式中不存在 ^和$符号时,使用了 m ,则:
正则表达式正常匹配字符串

④当正则表达式中不存在 ^和$符号时,没有使用了 m ,则
正则表达式正常匹配字符串

下面来具体看第二条注意中各种可能。

<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        
        var re=/^ad{2}$/m;
        var res=re.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");
        
        var re1=/^ad{2}$/;
        var res1=re1.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");
        
    </script>
</body>
</html>

断点查看结果:

1)var res=re.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");断点截图

这是情况①
当正则表达式中存在 ^和$符号时,使用了 m ,则:
“^”与字符串开始位置以及“\n”或“\r”之后的位置相匹配,
“$”与字符串结束位置以及“\n”或“\r”之前的位置相匹配。

m1.png

2)var res1=re1.exec("adfdd1727\r\naddjdsljs\r\nadd\nshshsh");断点截图

这是情况②
当正则表达式中存在 ^和$符号时,没有使用了 m ,则:
“^”与字符串的开始位置相匹配,
“$”与字符串的结束位置相匹配。

m2.png
<!DOCTYPE html>
<html>
<head>
    <title>exec()方法的使用</title>
    <meta charset="utf-8">
</head>
<body>
    <script type="text/javascript">
        
        var str="fdd1727\r\naddjdsljs\r\nadd\nshshsh";
        var re=/ad{2}/m;
        var res=re.exec(str);
        
        var re1=/ad{2}/;

        var res1=re1.exec(str);
        
    </script>
</body>
</html>

断点查看结果:

1)var res=re.exec(str); 断点截图

这是情况③
当正则表达式中不存在 ^和$符号时,使用了 m ,则:
正则表达式正常匹配整个要检索的字符串

m3.png

2)var res1=re1.exec(str);

这是情况④
当正则表达式中不存在 ^和$符号时,没有使用了 m ,则:
正则表达式正常匹配整个要检索的字符串


m4.png

综上所知:
使用m的时候,只有当 要检索的字符串中有换行符,且正则表达式中有 ^和$位置符号时,m才会起作用;
其他情况下使用和不使用m都当一个正常的字符串 匹配检索。


后记:
至于m的使用有些特殊,有大神能够讲的更清晰和把原理能讲清的还请不吝赐教,在此先行谢过啦。
路漫漫其修远兮,吾将上下而求索!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容