JavaScript使用正则表达式

正则表达式(RegExp)也称规则表达式(regular expression),是非常强大的字符串操作工具,语法格式为一组特殊字符构成的匹配模式,用来匹配字符串。ECMAScript 3以Perl为基础规范JavaScript正则表达式,实现Perl 5正则表达式的子集。JavaScript通过内置RegExp类型支持正则表达式,String和RegExp类型都提供执行正则表达式匹配操作的相关方法。

1、使用正则表达式

1.1、定义正则表达式

1.构造正则表达式

使用RegExp()构造函数可以定义正则表达式对象,具体语法格式如下:

    new RegExp(pattern, attributes)

其中,参数pattern是一个字符串,指定匹配模式或者正则表达式对象;参数attributes是一个可选的修饰性标志,包含g、i和m,分别用来设置全局匹配、区分大小写的匹配和多行匹配。如果参数pattern是正则表达式对象,则必须省略第二个参数。

RegExp()函数将返回一个RegExp实例对象,对象包含指定的匹配模式和匹配标志。

RegExp()函数将返回一个RegExp实例对象,对象包含指定的匹配模式和匹配标志。

提示:JavaScript正则表达式支持g、i、m、u和y 5个标志符,简单说明如下:

  • g:global缩写,定义全局匹配,正则表达式将在一行字符串范围内执行所有匹配。
  • i:insensitive缩写,定义不区分大小写匹配,正则表达式忽视字母大小写。
  • m:multiline缩写,定义多行字符串匹配。
  • m:ES6新增,允许对于Unicode字符串进行匹配。
  • y:ES6新增,开启黏滞模式匹配,允许设置匹配的精确位置。

【示例1】使用RegExp构造函数定义一个简单的正则表达式,希望匹配字符串中所有的字母a,不区分大小写,因此需要在第2个参数中设置g和i修饰词:

    var r = new RegExp("a","gi");                  //设置匹配模式为全局匹配,且不区分大小写
    var s = "JavaScript!=JAVA";                    //字符串直接量
    var a = s.match(r);                            //匹配查找
    console.log(a);                                //返回数组["a","a","A","A"]

【示例2】在正则表达式中可以使用特殊字符。下面示例的正则表达式将匹配字符串“JavaScript JAVA”中每个单词的首字母:

    var r = new RegExp("\\b\\w","gi");                  //构造正则表达式对象
    var s = "JavaScript JAVA";                          //字符串直接量
    var a = s.match(r);                                 //匹配查找
    console.log(a);                                     //返回数组["j", "J"]

在上面示例中,“\b"表示单词的边界,”\w"表示任意ASCII字符。由于在字符串中,反斜杠表示转义序列,为了避免误解,使用“\”替换所有“\”字符,使用双反斜杠表示斜杠自身。

2.正则表达式直接量

正则表达式直接量使用双斜杠作为分隔符进行定义,双斜杠之间包含的字符为正则表达式的字符模式,字符模式不能使用引号,标志字符放在最后一个斜杠的后面。其语法如下:

    /pattern/attributes

【示例】定义一个正则表达式直接量,然后直接调用:

    var r = /\b\w/gi;
    var s = "JavaScript JAVA";
    var a = s.match(r);                         //直接调用正则表达式直接量
    console.log(a);                             //返回数组["j", "J"]

提示:匹配模式不是字符串,对于RegExp()构造函数来说,它接收的参数全部是字符串,为了防止字符串被转义,需要使用双斜杠进行规避,而在正则表达式直接量中,每个字符都按正则表达式的语法规则定义,不需要考虑字符串的转义问题。

1.2、执行匹配

使用exec()方法可以执行通用匹配操作,具体语法格式如下:

    regexp.exec(string)

regexp表示正则表达式对象,参数string是要检索的字符串。返回一个数组,其中存放匹配的结果。如果未找到匹配结果,则返回null。

数组的第1个元素存储匹配的字符串,第2个元素是第1个子表达式匹配的文本(如果有),第3个元素是第2个子表达式匹配的文本(如果有),以此类推。

数组对象还会包含下面两个属性:

  • index:匹配文本的第一个字符的下标位置。
  • input:存放被检索的字符串,即参数string自身。

提示:在非全局模式下,exec()方法返回的数组与String.match()方法返回的数组是相同的。

在全局模式下,exec()方法、String.match()方法返回结果不同。当调用exec()方法时,会为正则表达式对象定义lastIndex属性,指定执行下一次匹配的起始位置,同时返回匹配数组,与非全局模式下的数组结构相同;而String.match()方法仅返回匹配文本组成的数组,没有附加信息。

因此,在全局模式下获取完整的匹配信息只能使用exec()方法。

当exec()方法找到与表达式相匹配的文本后,会重置lastIndex属性为匹配文本的最后一个字符下标位置加1,为下一次匹配设置起始位置。因此,通过反复调用exec()方法,可以遍历字符串,实现全局匹配操作,如果找不到匹配文本,将返回null,并重置lastIndex属性为0。

【示例】定义正则表达式,然后调用exec()方法,逐个匹配字符串中每个字符,最后使用while语句显示完整的匹配信息:

    var s = "JavaScript";                           //测试使用的字符串直接量
    var r = /\w/g;                                  //匹配模式
    while((a = r.exec(s)) ){                        //循环执行匹配操作
        console.log("匹配文本 = " + a[0] + " a.index = " + a.index + " r.lastIndex = " + r.lastIndex); //显示每次匹配操作后返回的
数组信息
    }

在while语句中,把返回结果作为循环条件,当返回值为null时,说明字符串检测完毕,立即停止迭代,否则继续执行。在循环体内,读取返回数组a中包含的匹配结果,并读取结果数组的index属性,以及正则表达式对象的lastIndex属性,演示效果如下图所示:
在这里插入图片描述
注意:正则表达式对象的lastIndex属性是可读可写的。使用exec()方法对一个字符串执行匹配操作后,如果再对另一个字符串执行相同的匹配操作,应该手动重置lastIndex属性为0,否则不会从字符串的第一个字符开始匹配,返回的结果也会不同。

1.3、检测字符串

使用test()方法可以检测一个字符串是否包含匹配字符串,语法格式如下:

    regexp.test(string)

regexp表示正则表达式对象,参数string表示要检测的字符串。如果字符串string中含有与regexp正则表达式匹配的文本,则返回true,否则返回false。

【示例】使用test()方法检测字符串中是否包含字符:

    var s = "JavaScript";
    var r = /\w/g;                         //匹配字符
    var b = r.test(s);                     //返回true

如果使用正则表达式进行匹配,则返回false,因为在字符串JavaScript中找不到数字:

    var r = /\d/g;                      //匹配数字
    var b = r.test(s);                  //返回false

1.4、编译表达式

使用compile()方法可以重新编译正则表达式对象,修改匹配模式。具体语法格式如下:

    regexp.compile(regexp,modifier)

参数regexp表示正则表达式对象,或者匹配模式字符串。当第一个参数为匹配模式字符串时,可以设置第二个参数modifier,如g、i、gi等。

    var s = "JavaScript";                         //测试字符串
    var r = /\w/g;                                //匹配模式
    var n=0
    while(r.test(s)){                             //循环执行匹配验证
        if(r.lastIndex == 3){                     //当匹配第4个字符时,调整匹配模式
            r.compile(/[A-Z]/g);                  //修改字符模式,定义仅匹配大写字母
           r.lastIndex = 3;                       //设置下一次匹配的起始位置
       }
       console.log("匹配文本 = " + RegExp.lastMatch + " r.lastIndex = " + r.lastIndex);
    }

在上面示例代码中,r.compile(/[A-Z]/g);可以使用r.compile(“[A-Z]”,“g”);代替。

注意:重新编译正则表达式之后,正则表达式所包含的信息都被恢复到初始化状态,如lastIndex变为0。如果想继续匹配,就需要设置lastIndex属性,定义继续匹配的起始位置。反之,当执行正则表达式匹配操作之后,如果想用该正则表达式继续匹配其他字符串,不妨利用下面方法恢复其初始状态,而不用手动重置lastIndex属性。

    regexp.compile(regexp);

其中regexp表示同一个正则表达式。
在这里插入图片描述

1.5、访问匹配信息

每个正则表达式对象都包含一组属性,说明如下表所示:
在这里插入图片描述
注意:global、ignoreCase、multiline和source属性都是只读属性。lastIndex属性可读可写,通过设置该属性,可以定义匹配的起始位置。

【示例】演示读取正则表达式对象的基本信息,以及lastIndex属性在执行匹配前后的变化:

    var s = "JavaScript";                                      //测试字符串
    var r = /\w/g;                                             //匹配模式
    console.log("r.global = " + r.global);                     //返回true
    console.log("r.ignoreCase = " + r.ignoreCase);             //返回true
    console.log("r.multiline = " + r.multiline);               //返回false
    console.log("r.source = " + r.source);                     //返回a
    console.log("r.lastIndex = " + r.lastIndex);               //返回0
    r.exec(s);                                                 //执行匹配操作
    console.log("r.lastIndex = " + r.lastIndex);               //返回1

1.6、访问RegExp静态信息

RegExp类型对象包含一组属性,通过RegExp对象直接访问,也称为静态信息。这组属性记录当前脚本中最新正则表达式匹配的详细信息,说明如下表所示:
在这里插入图片描述
提示:这些静态属性大部分有两个名字:长名(全称)和短名(简称,以美元符号开头表示)。

【示例1】演示RegExp类型静态属性使用,匹配字符串JavaScript:

    var s = "JavaScript,not JavaScript";
    var r = /(Java)Script/gi;
    var a = r.exec(s);                    //执行匹配操作
    console.log(RegExp.input);            //返回字符串“JavaScript,not JavaScript”
    console.log(RegExp.leftContext);      //返回空字符串,左侧没有内容
    console.log(RegExp.rightContext);     //返回字符串“,not JavaScript”
    console.log(RegExp.lastMatch);        //返回字符串JavaScript
    console.log(RegExp.lastParen);        //返回字符串Java

执行匹配操作后,各个属性的返回值说明如下:

  • input属性记录操作的字符串:“JavaScript,not JavaScript”。
  • leftContext属性记录匹配文本左侧的字符串,在第一次匹配操作时,左侧文本为空。而rightContext属性记录匹配文本右侧的文本,即为“,not JavaScript”。
  • lastMatch属性记录匹配的字符串,即为JavaScript。
  • lastParen属性记录匹配的分组字符串,即为Java。

如果匹配模式中包含多个子模式,则最后一个子模式所匹配的字符就是RegExp.lastParen:

    var r = /(Java)(Script)/gi;
    var a = r.exec(s);                              //执行匹配操作
    console.log(RegExp.lastParen);                  //返回字符串Script,而不再是Java

【示例2】针对上面示例也可以使用短名读取相关信息:

    var s = "JavaScript,not JavaScript";
    var r = /(Java)(Script)/gi;
    var a = r.exec(s);
    console.log(RegExp.$_);                          //返回字符串“JavaScript,not JavaScript”
    console.log(RegExp["$`"]);                       //返回空字符串
    console.log(RegExp["$'"]);                       //返回字符串“,not JavaScript”
    console.log(RegExp["$&"]);                       //返回字符串JavaScript
    console.log(RegExp["$+"]);                       //返回字符串Script

提示:这些属性的值都是动态的,在每次执行匹配操作时,都会被重新设置。

2、匹配模式语法基础

匹配模式是一组特殊格式的字符串,它由一系列特殊字符(也称元字符)和普通字符构成,每个元字符都包含特殊的语义,能够匹配特定的字符。

2.1、字符

根据正则表达式语法规则,大部分字符仅能够描述自身,这些字符称为普通字符,如所有的字母、数字等。

元字符就是拥有特定功能的特殊字符,大部分需要加反斜杠进行标识,以便与普通字符进行区别。而少数元字符,需要加反斜杠以便转义为普通字符使用。JavaScript正则表达式支持的元字符如下表所示:
在这里插入图片描述
表示字符的方法有多种,除了可以直接使用字符本身外,还可以使用ASCII编码或者Unicode编码表示。

【示例1】使用ASCII编码定义正则表达式直接量:

    var r = /\x61/;                        //以ASCII编码匹配字母a
    var s = "JavaScript";
    var a = s.match(r);                    //匹配第一个字符a

由于字母a的ASCII编码为97,被转换为十六进制数值后为61,因此如果要匹配字符a,就应该在前面添加“\x”前缀,表示ASCII编码。

【示例2】除了十六进制外,还可以使用八进制数值表示字符:

    var r = /\141/;                        //141是字母a的ASCII编码的八进制值
    var s = "JavaScript";
    var a = s.match(r);                    //即匹配第1个字符a

使用十六进制需要添加“\x”前缀,主要是避免语义混淆,但是八进制不需要添加前缀。

【示例3】ASCII编码只能够匹配有限的单字节字符,使用Unicode编码可以表示双字节字符。Unicode编码方式:“\u”前缀加上4位十六进制值:

    var r = /\u0061/;                      //以Unicode编码匹配字母a
    var s = "JavaScript";                  //字符串直接量
    var a = s.match(r);                    //匹配第一个字符a

2.2、字符范围

在正则表达式语法中,中括号表示字符范围。在中括号内可以包含多个字符,表示匹配其中任意一个字符。如果多个字符的编码顺序是连续的,可以仅指定开头和结尾字符,中间字符可以省略,仅使用连字符(-)表示。如果在中括号内添加脱字符(^)前缀,还可以表示范围之外的字符。例如:

  • [abc]:查找中括号内任意一个字符。
  • [^abc]:查找不在中括号内的字符。
  • [0-9]:查找0~9范围内的数字,即查找数字。
  • [a-z]:查找从小写a到小写z范围内的字符,即查找小写字母。
  • [A-Z]:查找从大写A到大写Z范围内的字符,即查找大写字母。
  • [A-z]:查找从大写A到小写z范围内的字符,即所有大小写的字母。

【示例1】字符范围遵循字符编码的顺序进行匹配。如果将要匹配的字符恰好在字符编码表中的特定区域内,就可以使用这种方式表示:
如果匹配任意ASCII字符: var r = /[\u0000-\u00ff]/g;
如果匹配任意双字节的汉字: var r = /[^\u0000-\u00ff]/g;
如果要匹配任意大小写字母和数字: var r = /[a-zA-Z0-9]/g;
使用Unicode编码设计,匹配数字: var r = /[\u0030-\u0039]/g;
使用下面字符模式可以匹配任意大写字母: var r = /[\u0041-\u004A]/g;
使用下面字符模式可以匹配任意小写字母: var r = /[\u0061-\u007A]/g;

【示例2】在字符范围内可以混用各种字符模式:

    var s = "abcdez";                     //字符串直接量
    var r = /[abce-z]/g;                  //字符a、b、c,以及e~z的任意字符
    var a = s.match(r);                   //返回数组["a","b","c","e","z"]

【示例3】在中括号内不要有空格,否则会误解为还要匹配空格:

    var r = /[0-9 ]/g;

【示例4】字符范围可以组合使用,以便设计更灵活的匹配模式:

    var s = "abc4 abd6 abe3 abf1 abg7";      //字符串直接量
    var r = /ab[c-g][1-7]/g;                 //前两个字符为ab,第三个字符为从c到g,
                                             ///第四个字符为1~7的任意数字
    var a = s.match(r);                      //返回数组["abc4"," abd6"," abe3"," abf1"," abg7"]

【示例5】使用反义字符范围可以匹配很多无法直接描述的字符,实现以少应多的目的:

    var r = /[^0123456789]/g;

在这个正则表达式中,将会匹配除了数字以外任意的字符。反义字符类比简单字符类的功能更加强大和实用。

2.3、选择匹配

选择匹配使用竖线(|)描述,表示在两个子模式的匹配结果中任选一个。

匹配任意数字或字母: var r = /\w+|\d+/; //选择重复字符类

可以定义多重选择模式。设计方法:在多个子模式之间加入选择操作符: var r = /(abc)|(efg)|(123)|(456)/; //多重选择匹配

`注意:为了避免歧义,应该为选择操作的多个子模式加上小括号。

2.4、重复匹配

在正则表达式语法中,定义了一组重复类量词,如下表所示。它们定义了重复匹配字符的确数或约数。
在这里插入图片描述

【示例】结合示例演示说明,先设计一个字符串:

    var s = "ggle gogle google gooogle goooogle gooooogle goooooogle gooooooogle goooooooogle"

如果仅匹配单词ggle和gogle,可以设计:

    var r = /go?gle/g;                   //匹配前一项字符o0次或1次
    var a = s.match(r);                  //返回数组["ggle", "gogle"]

量词“?”表示前面字符或子表达式为可有可无,等效于:

    var r = /go{0,1}gle/g;                  //匹配前一项字符o0次或1次
    var a = s.match(r);                     //返回数组["ggle", "gogle"]

如果匹配第4个单词gooogle,可以设计:

    var r = /go{3}gle/g;                  //匹配前一项字符o重复显示3次
    var a = s.match(r);                   //返回数组["gooogle"]

等效于:

    var r = /gooogle/g;                  //匹配字符gooogle
    var a = s.match(r);                  //返回数组["gooogle"]

如果匹配第4个到第6个之间的单词,可以设计:

    var r = /go{3,5}gle/g;                  //匹配第4~6的单词
    var a = s.match(r);                     //返回数组["gooogle", "goooogle", "gooooogle"]

如果匹配所有单词,可以设计:

    var r = /go*gle/g;   //匹配所有的单词
    var a = s.match(r);  //返回数组["ggle", "gogle", "google", "gooogle", "goooogle", "gooooogle", "goooooogle", "goooooooogle",
"gooooooooogle"]

量词“*”表示前面字符或子表达式可以不出现,或者重复出现任意多次。

等效于:

    var r = /go{0,}gle/g; //匹配所有的单词
    var a = s.match(r);   //返回数组["ggle", "gogle", "google", "gooogle", "goooogle", "gooooogle", "goooooogle", "goooooooogle",
"gooooooooogle"]

如果匹配包含字符“o”的所有单词,可以设计:

    var r = /go+gle/g;                      //匹配的单词中字符“o”至少出现1次
    var a = s.match(r);  //返回数组["gogle", "google", "gooogle", "goooogle", "gooooogle", "goooooogle", "goooooooogle",
"gooooooooogle"]

量词“+”表示前面字符或子表达式至少出现1次,最多重复次数不限。

等效于:

    var r = /go{1,}gle/g; //匹配的单词中字符"o"至少出现1次
    var a = s.match(r);   //返回数组["gogle", "google", "gooogle", "goooogle", "gooooogle", "goooooogle", "goooooooogle",
"gooooooooogle"]

注意:重复类量词总是出现在它们所作用的字符或子表达式后面。如果想作用多个字符,需要使用小括号把它们包裹在一起形成一个子表达式。

2.5、惰性匹配

重复类量词都具有贪婪性,在条件允许的前提下,会匹配尽可能多的字符:

  • ?、{n}和{n, m}重复类具有弱贪婪性,表现为贪婪的有限性。
  • *、+和{n, }重复类具有强贪婪性,表现为贪婪的无限性。

【示例1】排在左侧的重复类量词的匹配优先级更高。当多个重复类量词同时满足条件时,会在保证右侧重复类量词最低匹配次数基础上,最左侧的重复类量词将尽可能地占有所有字符:

    var s ="<html><head><title></title></head><body></body></html>";
    var r = /(<.*>)(<.*>)/
    var a = s.match(r);
                        //左侧子表达式匹配"<html><head><title></title></head><body></body>"
    console.log(a[1]);
    console.log(a[2]);  //右侧子表达式匹配"</html>"

与贪婪匹配相反,**惰性匹配将遵循另一种算法:在满足条件的前提下,尽可能少地匹配字符。**定义惰性匹配的方法:在重复类量词后面添加问号(?)限制词。贪婪匹配体现最大化匹配原则,惰性匹配则体现最小化匹配原则。

【示例2】演示定义惰性匹配模式:

    var s ="<html><head><title></title></head><body></body></html>";
    var r = /<.*?>/
    var a = s.match(r); //返回单个元素数组["<html>"]

在上面示例中,对于正则表达式/<.*?>/来说,它可以返回匹配字符串“<>”,但是为了能够确保匹配条件成立,在执行中还是匹配带有4个字符的字符串“html”。惰性取值不能够以违反模式限定的条件而返回,除非没有找到符合条件的字符串,否则必须满足它。

2.6、边界

边界就是确定匹配模式的位置,如字符串的头部或尾部,具体说明如下表所示:
在这里插入图片描述

【示例】演示使用边界量词。先定义字符串:

    var s = "how are you";

匹配最后一个单词:

    var r = /\w+$/;
    var a = s.match(r);              //返回数组["you"]

匹配第一个单词:

    var r = /^\w+/;
    var a = s.match(r);              //返回数组["how"]

匹配每一个单词:

    var r = /\w+/g;
    var a = s.match(r);              //返回数组["how", "are" , "you"]

2.7、条件声明

声明量词表示条件的意思。声明量词包括正向声明和反向声明两种模式。

1.正向声明

正向声明是指定匹配模式后面的字符必须被匹配,但又不返回这些字符。语法格式如下:

    匹配模式(?=匹配条件)

声明包含在小括号内,它不是分组,因此作为子表达式:

    var s = "one:1;two=2";
    var r = /\w*(?==)/;             //使用正向声明,指定执行匹配必须满足的条件
    var a = s.match(r);             //返回数组["two"]

在上面示例中,通过(?==)锚定条件,指定只有在\w*所能够匹配的字符后面跟随一个等号字符,才能够执行\w*匹配。所以,最后匹配的是字符串two,而不是字符串one。

2.反向声明

与正向声明匹配相反,反向声明是指定接下来的字符都不必匹配。语法格式如下:

    匹配模式(?!匹配条件)

【示例2】定义一个反向声明的匹配模式:

    var s = "one:1;two=2";
    var r = /\w*(?!=)/;                 //使用反向声明,指定执行匹配不必满足的条件
    var a = s.match(r);                 //返回数组["one"]

在上面示例中,通过(?!=)锚定条件,指定只有在“\w*”所能够匹配的字符后面不跟随一个等号字符,才能够执行\w*匹配。所以,最后匹配的是字符串one,而不是字符串two。

2.8、子表达式

使用小括号可以对字符模式进行任意分组,在小括号内的字符串表示子表达式,也称为子模式。子表达式具有独立的匹配功能,保存独立的匹配结果。同时,小括号后的量词将会作用于整个子表达式。

通过分组可以在一个完整的字符模式中定义一个或多个子模式。当正则表达式成功地匹配目标字符串后,也可以从目标字符串中抽出与子模式相匹配的子内容。

【示例】在下面代码中,不仅匹配出每个变量声明,同时还抽出每个变量及其值:

    var s ="ab=21,bc=45,cd=43";
    var r = /(\w+)=(\d*)/g;
    while(a = r.exec(s)){
        console.log(a);               //返回类似 ["ab=21" , "ab","21"]三个数组
    }

2.9、反向引用

在字符模式中,后面的字符可以引用前面的子表达式,实现方法如下:

    \数字

数字指定子表达式在字符模式中的顺序。如“\1”引用的是第1个子表达式,“\2”引用的是第2个子表达式。

【示例1】在下面代码中,通过引用前面子表达式匹配的文本,以实现成组匹配字符串:

    var s ="<h1>title<h1><p>text<p>";
    var r = /(<\/?\w+>).*\1/g;
    var a = s.match(r);                //返回数组["<h1>title<h1>" , "<p>text<p>"]

提示:由于子表达式可以相互嵌套,它们的顺序将根据左括号的顺序确定。例如,下面示例定义匹配模式包含多个子表达式:

    var s = "abc";
    var r = /(a(b(c)))/;
    var a = s.match(r);               //返回数组["abc", "abc" , "bc" , "c"]

在这个模式中,共产生3个反向引用,第一个是“(a(b(c)))”,第二个是“(b(c))”,第三个是“(c)”,它们引用的匹配文本分别是字符串abc、bc和c。

注意:对子表达式的引用,是指引用前面子表达式所匹配的文本,而不是子表达式的匹配模式。如果要引用前面子表达式的匹配模式,则必须使用下面方式,只有这样才能够达到匹配的目的。

    var s ="<h1>title</h1><p>text</p>";
    var r = /((<\/?\w+>).*(<\/?\w+>))/g;
    var a = s.match(r);                   //返回数组["<h1>title</h1>","<p>text</p>"]

反向引用在开发中主要有以下几种常规用法:
【示例2】在正则表达式对象的test()方法,以及字符串对象的match()和search()等方法中使用。在这些方法中,反向引用的值可以从RegExp()构造函数中获得。

    var s = "abcdefghijklmn";
    var r = /(\w)(\w)(\w)/;
    r.test(s);
    console.log(RegExp.$1);            //返回第1个子表达式匹配的字符a
    console.log(RegExp.$2);            //返回第2个子表达式匹配的字符b
    console.log(RegExp.$3);            //返回第3个子表达式匹配的字符c

通过上面示例可以看到,正则表达式执行匹配测试后,所有子表达式匹配的文本都被分组存储在RegExp()构造函数的属性内,通过前缀符号$与正则表达式中子表达式的编号引用临时属性。其中,属性$1标识符指向第一个值引用,属性$2标识符指向第二个值引用,以此类推。

【示例3】可以直接在定义的字符模式中包含反向引用。这可以通过使用特殊转义序列(如\l、\2等)来实现:

    var s = "abcbcacba";
    var r = /(\w)(\w)(\w)\2\3\1\3\2\1/;
    var b = r.test(s);                   //验证正则表达式是否匹配该字符串
    console.log(b);                      //返回true

在上面示例的正则表达式中,“\1”表示对第一个反向引用(\w)所匹配的字符a引用,“\2”表示对第二个反向引用(\w)所匹配的字符b引用,“\3”表示对第二个反向引用(\w)所匹配的字符c引用。

【示例4】可以在字符串对象的replace()方法中使用,通过使用特殊字符序列$1、$2、$3等实现。例如,将颠倒相邻字母和数字的位置。

    var s = "aa11bb22c3d4e5f6";
    var r = /(\w+?)(\d+)/g;
    var b = s.replace(r,"$2$1");
    console.log(b);               //返回字符串“11aa22bb3c 4d5e6f”

在上面例子中,正则表达式包括两个分组:第一个分组匹配任意连续的字母;第二个分组匹配任意连续的数字。在replace()方法的第二个参数中,$1表示对正则表达式中第一个子表达式匹配文本的引用,而$2表示对正则表达式中第二个子表达式匹配文本的引用,通过颠倒$1和$2标识符的位置,即可实现字符串的颠倒替换原字符串。

2.10、禁止引用

反向引用会占用一定的系统资源,在较长的正则表达式中,反向引用会降低匹配速度。如果分组仅仅是为了方便操作,可以禁止反向引用。实现方法:在左括号的后面加上一个问号和冒号。

【示例】演示禁止引用:

    var s1 = "abc";
    var r = /(?:\w*?)|(?:\d*?)/;        //非引用型分组
    var a = r.test(s1);                 //返回true

非引用型分组对于必须使用子表达式,但是又不希望存储无用的匹配信息,或者希望提高匹配速度,是非常重要的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/120315.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小米手机怎么识别图片上的表格文字?

前言&#xff1a; 小米手机怎么识别图片上的文字&#xff1f;有二种解决方案&#xff1a;一是直接用系统自带的OCR工具来实现&#xff0c;二是借助第三方软件&#xff08;如金鸣识别&#xff09;来实现。 一、用小米自带的系统工具来实现。 对于MIUI12.5以上系统的小米手机来…

学C++跟着视频学还是跟着书学?

学C跟着视频学还是跟着书学&#xff1f; 感觉得看基础和目标 如果不是喜欢 C 或者以求职 / 完成 C 相关工作为目标的话&#xff0c;菜鸟教程其实都够了&#xff0c;基本语法掌握就差不多&#xff0c;然后多去写。 最近很多小伙伴找我&#xff0c;说想要一些C的资料&#xff0…

如何在在线Excel文档中对数据进行统计

本次我们将用zOffice表格的公式与数据透视表分析样例&#xff08;三个班级的学生成绩&#xff09;。zOffice表格内置了大量和Excel相同的统计公式&#xff0c;可以进行各种常见的统计分析&#xff0c;如平均值、标准差、相关性等。同时&#xff0c;zOffice也有数据透视表功能&a…

【Web】在前端中,HTML<meta>标签

<meta>实例 <head><meta name"description" content"免费在线教程"><meta name"keywords" content"HTML,CSS,XML,JAVASCRIPT"><meta name"author" content"runoob"><meta char…

java高级之单元测试、反射

1、Junit测试工具 Test定义测试方法 1.被BeforeClass标记的方法,执行在所有方法之前 2.被AfterCalss标记的方法&#xff0c;执行在所有方法之后 3.被Before标记的方法&#xff0c;执行在每一个Test方法之前 4.被After标记的方法&#xff0c;执行在每一个Test方法之后 public …

相亲交友小程序源码 同城相亲交友小程序源码

相亲交友小程序源码 同城相亲交友小程序源码 收费模式&#xff1a; 1、会员开通VIP收费&#xff1b;3、会员购买服务项目收费&#xff08;可以自定义服务项目&#xff09;&#xff1b; 二、全民推广系统&#xff1a; 1、邀请用户注册奖励&#xff08;邀请一个用户进入注册…

一个数组实现两个栈

一个数组实现两个栈 基本思路&#xff1a; 1.定义两个栈顶top1-1&#xff0c;top2maxsize 2.栈满&#xff0c;当top1与top2相差1时栈满 package 例题; //一个数组实现两个栈 public class TwoStack {private int[] arr;private int maxSize;//定义栈顶private int top1;private…

C# TCP Server服务端多线程监听RFID读卡器客户端上传的读卡数据

本示例使用设备介绍&#xff1a;液显WIFI无线网络HTTP协议RFID云读卡器可编程实时可控开关TTS语-淘宝网 (taobao.com) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using Sy…

mindspore mindcv图像分类算法;模型保存与加载

参考&#xff1a; https://www.mindspore.cn/tutorials/en/r1.3/save_load_model.html https://github.com/mindspore-lab/mindcv/blob/main/docs/zh/tutorials/finetune.md 1、mindspore mindcv图像分类算法 import os from mindcv.utils.download import DownLoad import o…

移远EC600U-CN开发板 day03

控件探索-按钮&#xff08;lv.btn&#xff09; (1) 创建并显示一个按钮 * 核心代码 btn lv.btn(scr) #将按钮与src对象关联 btn.align(lv.ALIGN.CENTER,0,0) #居中显示&#xff08;第1个0表示x的偏移量&#xff0c;第2个0表示相对于y的偏移量&#xff09; label lv.l…

小白学爬虫:手机app分享商品短连接获取淘宝商品链接接口|淘宝淘口令接口|淘宝真实商品链接接口|淘宝商品详情接口

通过手机APP分享的商品短链接&#xff0c;我们可以调用相应的接口来获取淘口令真实URL&#xff0c;进而获取到PC端的商品链接及商品ID。具体步骤如下&#xff1a; 1、通过手机APP分享至PC端的短链接&#xff0c;调用“item_password”接口。 2、该接口将返回淘口令真实URL。 3…

从使用的角度看 ByConity 和 ClickHouse 的差异

自 ClickHouse Inc 宣布其重要新功能仅在 ClickHouse Cloud 上开放以来&#xff0c;一些关注 ByConity 开源的社区小伙伴也来询问 ByConity 后续开源规划。为回答社区疑问&#xff0c;我们将之前分享的关于 ByConity 与 ClickHouse 相关功能对比的 webinar 整理为文章&#xff…

Git 基础知识回顾及 SVN 转 Git 自测

背景 项目开发过程中使用的版本控制工具是 SVN&#xff0c;Git 多有耳闻&#xff0c;以前也偶尔玩过几次&#xff0c;但是工作中不用&#xff0c;虽然本地也有环境&#xff0c;总是不熟练。 最近看一本网络开源技术书时&#xff0c;下载源码部署了一下&#xff0c;又温故了一…

助力工业数字化!TDengine 与恩菲 MIM+ 工业互联网平台实现兼容性互认

在云计算、物联网、5G等新兴技术快速发展的当下&#xff0c;制造企业想要运用新兴技术实现数字化转型&#xff0c;工业互联网平台的应用和打造是非常关键的转型要素。在工业互联网平台的发展中&#xff0c;数据处理上存在的问题一直都是令企业所头疼的&#xff0c;越来越多的案…

Java并发编程第11讲——AQS设计思想及核心源码分析

Java并发包&#xff08;JUC&#xff09;中提供了很多并发工具&#xff0c;比如前面介绍过的ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore、FutureTask等锁或者同步部件&#xff0c;它们的实现都用到了一个共同的基类——AbstractQueuedSynchronizer&…

汽车网络安全渗透测试概述

目录 1.汽车网络安全法规概述 1.1 国外标准 1.2 国内标准 2.汽车网络安全威胁分析 2.1 汽车网络安全资产定义 2.2 汽车网络安全影响场景及评级示例 3.汽车网络安全渗透测试描述 3.1 参考法规 3.2 渗透测试内容 4.小结 1.汽车网络安全法规概述 近年来&#xff0c;汽车…

【UE4】UE编辑器乱码问题

环境&#xff1a;UE4.27、vs2019 如何解决 问题原因&#xff0c;UE的编码默认是UTF-8&#xff0c;VS的默认编码是GBK 通过"高级保存选项" 直接修改VS的 .h头文件 的 编码 为 UTF-8 步骤1. 步骤2. 修改编码后&#xff0c;从新编译&#xff0c;然后就可以解决编辑器…

很多个pdf怎么合并在一起?

很多个pdf怎么合并在一起&#xff1f;作为一个办公室的伙伴&#xff0c;对于PDF格式肯定不会陌生。它强大的功能为我们的工作提供了许多便利。由于PDF文件格式的稳定性和安全性较高&#xff0c;我们通常在工作或学习中使用它来传输文件&#xff0c;很多人都喜欢将办公文件都做成…

Java用log4j写日志

日志可以方便追踪和调试问题&#xff0c;以前用log4net写日志&#xff0c;换Java了改用log4j写日志&#xff0c;用法和log4net差不多。 到apache包下载下载log4j的包&#xff0c;解压后把下图两个jar包引入工程 先到网站根下加一个log4j2.xml的配置文件来配置日志的格式和参…

自动驾驶行业观察之2023上海车展-----车企发展趋势(3)

合资\外资发展 宝马&#xff1a;i7、iX1新车亮相&#xff0c;未来将持续发力电动化、数字化&#xff08;座舱&#xff09; 宝马在本次车展重点展示了电动化产品&#xff0c;新发车型为i7 M70L、iX1、及i vision Dee概念车等车型。 • 展示重点&#xff1a;电动化数字化&#…