JavaScript 学习笔记(十四) 正则表达式

  RegExp类

  RegExp对象的构造函数可以带一个或两个参数

  第一个参数是描述需要进行匹配的模式字符串,如果还有第二个参数,这个参数则制定了额外的处理指令。

  一、基础

  1.1使用RegExp对象

  test()方法

  测试是否匹配。如果给定字符串(只有一个参数)匹配这个模式,它就返回true,否则返回false

  

复制代码 代码如下:

  var sToMatch = "cat";

  var reCat = /cat/; //正则表达式字面量使用Perl风格的语法

  alert(reCat.test(sToMatch)); //outs "true"

  exec()方法

  有一个字符串参数,返回一个数组。数组中的第一个条目是第一个匹配,其他的是反向引用。(即数组中只有一个,并且是第一个匹配的)

  

复制代码 代码如下:

  var strAAA = "a bat, a Cat, a fAt baT, a faT cat";

  var regAt = new RegExp("at", "gi");

  var arr = regAt.exec(strAAA); //arr[0]为"at",arr.index值为3,arr.lastIndex值为5

  match()方法

  返回一个包含在字符串中的所有匹配的数组。

  var strAAA = "a bat, a Cat, a fAt baT, a faT cat";

  var regAt = new RegExp("at", "gi");

  var arrMatch = strAAA.match(regAt); //注意:字符串.match(参数是匹配字符)跟上面相反

  search()方法

  与indexOf()有些类似,返回在字符串中出现的一个匹配的位置。它的参数是一个RegExp对象而非仅仅一个子字符串。

  

复制代码 代码如下:

  var strAAA = "a bat, a Cat, a fAt baT, a faT cat";

  var regAt = new RegExp("at", "gi");

  var index = strAAA.search(regAt); //outputs "3" 第一次出现位置是3

  1.2扩展字符串方法

  replace()方法

  可以用第二个参数替换第一个参数,而在这里第一个参数也可以是一个正则表达式。

  var strBBB = "The Sky is red.";

  //将上面这句话中的所有s替换,用正则表达式找出所有匹配的

  var strNewBBB = strBBB.replace(/s/gi, "##"); //把所有的“s”(不管大小写)都替换成##

  再进行升级一下,第二个参数也可以是一个函数

  

复制代码 代码如下:

  var sToChange = "The sky is red.";

  var reRed = /red/;

  var sResultText = sToChange.replace(reRed, function(sMatch) {

  return "blue";

  });

  alert(sResultText);

  在这个例子中,在函数中的sMatch的值总为"red" (因为这是唯一匹配的模式)."red"的首次出现被替换为函数的返回值"blue".

  附加:

  对于书上这句话“因为这是唯一匹配的模式”我认为应该是这个意思吧,replace只有两个参数,第一个参数找出来的是唯一的,那个function的参数sMatch应该就是前面的第一个参数的值,唯一匹配模式。。。

  split()方法

  

复制代码 代码如下:

  var sColor = "red,blue,yellow,green";

  var reComma = /\,/;

  var arrColors = sColor.split(reComma); //split at each comma

  alert(arrColors.length); //outputs "4"

  正则表达式reComma中必须在逗号前有一个反斜杠,因为逗号在语法中有特殊含义,必须经过转义。

  二、简单模式

  2.1元字符

  正则表达式用到的所有元字符有:

  ( [ { \ ^ $ | ) ? * + .

  一共12个。在任何时候要用到这些元字符的时候就需要转义,也就是在前面加上反斜杠。

  例:

  var reQMark = /\?/; //转义

  var reQMark=new RegExp("\\?"); //这里需要注意,双重转义,因为本身反斜杠也是需要转义

  所以我们以后应该尽量使用第一种情况,字面量语法!Perl的风格

  2.2使用特殊字符

  另外,还有其他一些预定义的特殊字符,如下表所列:

  字符 描述

  ----------------------------------------------------

  \t 制表符

  \n 换行符

  \r 回车符

  \f 换页符

  \a alert字符

  \e escape字符

  \cX 与X相对应的控制字符

  \b 回退字符

  \v 垂直制表符

  \0 空字符

  ----------------------------------------------------

  2.3字符类

  将一些字符放入方括号中,可以很有效的告诉正则表达式去匹配第一个、第二个、第三个字符等等。

  //①字符类----简单类

  var sToMatch = "a bat,a Cat,a fAt baT,a faT cat";

  //匹配以bat或cat或fat的正则表达式

  var reBatCatFat = /[bcf]at/gi;

  //var reBatCatRat=/[\u0062cf]at/gi; 使用Unicode形式

  var arrMatches = sToMatch.match(reBatCatRat);

  alert(arrMatches.join(",")); //输出"bat,Cat,fAt,baT,faT,cat"

  //②字符类----负向类

  var sToMatch = "a bat,a Cat,a fAt baT,a faT cat";

  //匹配以at结尾,但是不以b或c开头的正则表达式

  var reBatCatRat = /[^bc]at/gi; //脱字符^表示不能匹配后面跟着的字符

  var arrMatches = sToMatch.match(reBatCatRat);

  alert(arrMatches.join(",")); //输出 "fAt,faT"

  //③字符类----范围类

  //指定从a到z之间的范围:[a-z]. 这里是区分大小写的

  var sToMatch = "num1,num2,num3,num4,num5,num6,num7,num8,num9";

  var reOneToFour = /num[1-4]/gi; //从1到4

  var arrMatches = sToMatch.match(reOneToFour);

  alert(arrMatches.join(",")); //输出 "num1,num2,num3,num4"

  //④字符类----组合类

  组合类(combination class)是由几种其他的类组合而成的字符类.

  假如要匹配所有的从a-m的字母以及从1-4的数字,以及一个换行符,那么所用到的类应该是这样:

  [a-m1-4\n]

  注意在内部的类之间不要有空格.

  //⑤字符类----预定义类

  代码 等同于 匹配

  ----------------------------------------------------------------

  . [^\n\r] 除了换行和回车之外的任意字符

  \d [0-9] 数字

  \D [^0-9] 非数字字符

  \s [ \t\n\x0B\f\r] 空白字符

  \S [^ \t\n\x0B\f\r] 非空白字符

  \w [a-zA-Z_0-9] 单词字符(所有的字符、数字和下划线)

  \W [^a-zA-Z_0-9] 非单词字符

  -----------------------------------------------------------------

  使用预定义字符可以明显地使模式匹配变得简单。例如,假设想匹配3个数字:

  var sToMatch = "567 9838 abc";

  var reThreeNums = /[0-9][0-9][0-9]/;

  //var reThreeNums=/\d\d\d/; //用预定义比较简洁

  alert(reThreeNums.test(sToMatch)); //输出 "true"

  2.4量词

  量词(quantifier)可以指定某个特定模式出现的次数。当指定某个模式应当出现的次数时,可以指定硬性数量,也可以指定软性数量。

  1.简单量词

  --------------------------------------------------------------------

  代码 描述

  --------------------------------------------------------------------

  ? 出现零次或一次

  * 出现零次或多次(任意次)

  + 出现一次或多次(至少出现一次)

  {n} 一定出现n次

  {n,m} 至少出现n次但不超过m次

  {n,} 至少出现n次

  --------------------------------------------------------------------

  例如,假设想匹配单词bread,read或red.使用问号量词,则可以只要使用一个表达式就可以匹配这三个:

  var reBreadReadOrRed = /b?rea?d/;

  或者var reBreadReadOrRed = /b{0,1}rea{0,1}d/;

  2.贪婪的、惰性的和支配性的量词

  贪婪量词先看整个的字符串是否匹配。如果没有发现匹配,它去掉该字符串中的最后一个字符,并再次尝试。如果还是没有发现匹配,那么再次去掉最后一个字符,这个过程会一直重复直至到发现一个匹配或者字符串不剩任何字符。

  懒性量词先看字符串中的第一个字母是否匹配。如果单独这个字符还不够,就读入下一个字符,组成两个字符的字符串。如果还是没有发现匹配,惰性量词继续从字符串中添加字符直到发现匹配或者整个字符串都检查过也没有匹配。惰性量词和贪婪量词的工作方式恰好相反。

  支配量词只尝试匹配整个字符串。如果整个字符串不能产生匹配,不做进一步尝试。支配量词其实简单的说,就是一刀切。

  --------------------------------------------------------------------

  贪婪 惰性 支配 描述

  --------------------------------------------------------------------

  ? ?? ?+ 零次或一次出现

  * *? *+ 零次或多次出现

  + +? ++ 一次或多次出现

  {n} {n}? {n}+ 恰好n次出现

  {n,m} {n,m}? {n,m}+ 至少n次至多m次出现

  {n,} {n,}? {n,}+ 至少n次出现

  --------------------------------------------------------------------

  看下面例子更好的理解以上三种量词

  var str = "abbbaabbbaaabbb1234";

  var reg1 = /.*bbb/g;

  var reg2 = /.*?bbb/g;

  //var reg3 = /.*+bbb/g; //在Visual Studio2008里报错.....

  var arrMatches1 = str.match(reg1);

  var arrMatches2 = str.match(reg2);

  //var arrMatches3 = str.match(reg3);

  alert("贪婪的:" + arrMatches1.join(",") + "\n惰性的:" + arrMatches2.join(","));

  主要是匹配的一个过程不同!