正则表达式学习笔记

/*
  正则表达式
  JS 对正则表达式的支持是通过ECMAScript中的RegExp类实现的。
  RegExp对象的构造函数可以带一个或两个参数。
  第一个参数(或只有一个参数)是描述需要进行匹配的模式字符串,
  如果还有第二个参数,这个参数则指定了额外的处理指令。
**/
/**
 * 最基本的正则表达式就是一个普通的字符串。
 * 例如:要匹配单词"cat",可以定义如下的正则表达式:
 * */
  var reCat = new RegExp("cat");
  
/**
 * 带第二个参数的正则表达式,g->global的缩写,表示要搜索字符串中出现的全部"cat",
 * 而不是在找到第一个匹配后就停止。
 * 如果还要让模式不区分大小写,可以给第二个参数添加字符i->insensitive的缩写
 * 如下所示:
 */
  var reCat = new RegExp("cat",'gi');
  var reCat = /cat/gi;//两个等价

  /*
    1.test()方法
      判断字符串是否匹配,如果有一个匹配都返回true
      用法如下:
  */
  var str = 'cat';
  var regCat = /cat/;
  console.log(regCat.test(str));//true

/**
 * 2. exec()方法
 * 返回一个数组,数组中的第一个条目是第一个匹配,其他的反向引用
 *  用法如下:
*/
var str = 'cat bat oat ttdcccccatdddAt';
var regCat = /at/gi;
console.log(regCat.exec(str));//["at", index: 1, input: "cat bat oat ttdcccccatdddAt", groups: undefined]

/**
 * 3. match()方法
 *  返回一个包含在字符串中所有的匹配的数组
 * 这个方法跟上面两个方式的使用方式不同:
 * 这个方法调用string对象,同时传给它一个RegExp对象;
 * 用法如下:
 * **/
  var str = 'cat bat oat ttdcccccatdddAt';
  var regCat = /at/gi;
  console.log(str.match(regCat));//["at", "at", "at", "at", "At"]

/**
 * 4. replace()方法
 *  该方法也可以接受正则表达式作为第一个参数,
 * 也可以用另一个字符串作为第二个参数来替换某个字串(第一个参数的所有匹配项)
 * 第二个参数也可以是一个函数,函数里面接受一个参数,即匹配了的文本,该函数返回进行替换的文本
 * **/
var str = "the sky is red, flower is red.";
var regStr = /red/g;
console.log(str.replace("red", "blue"))//"the sky is blue, flower is red."
console.log(str.replace(regStr, "blue"))//"the sky is blue, flower is blue."
var strResult = str.replace(regStr, function(sMatch){return "blue"})

/***
 * 5. split()方法(将字符串转换为数组)
 *  该方法可以将字符串分割成一系列字串并通过一个数组将它们返回,
 *  用法如下:
 * **/
  var sColor = "red,blue,yellow,green";
  var regComma = /\,/;
  var arrColors = sColor.split(",")// ["red", "blue", "yellow", "green"]
  var arrColors = sColor.split(regComma)// ["red", "blue", "yellow", "green"]

  /**
   *  正则表达式进阶篇
   * **/
  /**
   * 1. 元字符:( [ {  ^ $ | ) ? * + . ,
   * 任何时候要在正则表达式中使用这些元字符,都必须对它们进行转义,
   * 如,要匹配一个问号,正则表达式应该这样表示:
   * 
   * **/
  var reQMark = /?/;

  /***
   * 2. 使用特殊字符
   *  可以通过直接使用字符来表示它们本身,也可以使用它们的ASCII代码或者Unicode代码指定字符
   * 特殊字符如下:
   *    ===>制表符;   ===> 换行符;   ===> 回车符; f ===> 换页符
   *  e ===> escape字符; cX ===> 与X相对应的控制字符;  ===> 回退符
   *  v ===> 垂直制表符;  ===> 空字符;
   * 如果通过RegExp构造函数来使用它们,则都必须进行双重转义
   * 假设想删除字符串中所有的换行符(常用于处理用户输入的文本)
   * **/
  var str = sStringNewLines.replace(/ /g, '');

  /**
   *  字符类
   * 字符流是用于测试的字符的组合。
   * 通过将一些字符放入方括号中,可以很有效地告诉正则表达式去匹配第一个字符、第二个字符、第三个字符等等。
   * 
   * **/
  /**
   *  1> 简单类
   *  如:想匹配'bat','cat'和'fat'
   * **/
  var str = "a bat, a Cat, a Fat Bat,a fAt cat";
  var regBatCatFat = /[bcf]at/gi;
  var regResult = str.match(regBatCatFat);// ["bat", "Cat", "Fat", "Bat", "fAt", "cat"]

  /**
   *  2> 负向类
   * 脱字符号(^):指定要排除的字符,告诉正则表达式字符不能匹配后面跟着的字符
   * ***/
  var str = "a bat, a Cat, a Fat Bat,a fAt cat";
  var regFat = /[^bc]at/gi;
  var regResult = str.match(regBatCatFat);//  ["Fat", "fAt"]

  /**
   *  3> 范围符
   *  [a-z],[0-9]
   * 
   * **/
  /**
   *  范围符与负向类结合使用:
   *  [^1-4]:不包含1-4这个范围
   * **/
  /**
   * 4> 组合类
   * 是由几种其他的类组合而成的字符类,
   * 如:要匹配所有的从a~m的字母以及从1~4的数字,以及一个换行符:
   *  [a-m1-4 ]
   * 注意在内部的类之间不要有空格
   * ***/
  /***
   * 5.预定义类
   * 由于某些模式会反复用到,所以可以使用一组预定义字符类以让我们更方便地指定复杂类。
   *  .   <===> [^ ]  除了换行和回车之外的任意字符
   *  d  <===> [0-9]    数字
   *  D  <===> [^0-9]   非数字字符
   *  s  <===> [  x0Bf ]  空白字符
   *  S  <===> [^  x0Bf ]  非空白字符
   *  w  <===> [a-zA-Z_0_9]  单词字符(所有的字母、所有的数字和下划线)
   *  W  <===> [^a-zA-Z_0_9]  非单词字符
   * **/
  /**
   * 6. 量词
   *  可以指定某个特定模式出现的次数。
   *  当指定摸个模式应当出现的次数时,可以指定硬性数量(例如:某个字符应该出现三次)
   *  也可以指定软性数量(例如,这个字符至少应该出现一次,不过可以重复任意次)
   *  ?     ==> 出现零次或一次                  ba?d         "bd","bad"
   *  *     ==> 出现零次或多次(任意次)         ba*d         "bd","bad","baad","baaad"
   *  +     ==> 出现一次或多次(至少出现一次)    ba+d         "bad","baad","baaad"
   *  {n}   ==> 一定出现n次                     ba{1}d       "bad"
   *  {n,m} ==> 至少出现n次但不超过m次           ba{0,1}d    "bd", "bad"
   *  {n, } ==> 至少出现n次                     ba{1,}d     "bad","baad","baaad"
   *  
   * **/

   /**
    * 7. 贪婪的、惰性的和支配性的量词
    *  1. 贪婪量词先看整个字符串是否匹配。如果没有发现匹配,它去掉该字符串中的最后一个字符,并再次尝试。
    *   如果还是没有发现匹配,那么再次去掉最后一个字符,
    *   这个过程会一直重复直到发现一个匹配或者整个字符串不剩任何字符。
    *   到目前为止讨论的所有量词都是贪婪的。
    *   
    *   2. 惰性量词:(在贪婪性量词后面加上?)
    *     ?? / *? / +? / {n}? / {n,m}? / {n, }?
    *   先看字符串中的第一个字母是否匹配。
    *   如果单独这个字符还不够,就读入下一个字符,组成两个字符的字符串。
    *   如果还是没有发现匹配,惰性量词继续从字符串中添加字符直到发现匹配或者整个字符串都检查过也没有匹配
    *   
    *   3. 支配性量词:(在贪婪性量词后面加上+)
    *   ?+ / *+ / ++ / {n}+ / {n,m}+ / {n, }+
    *   只尝试匹配整个字符串。如果整个字符串不能产生匹配,不做进一步尝试。
    *   支配性量词其实简单的说,就是一刀切。
    * 
    * **/



        var str = "abbbaabbbaaabbb1234";
        var re1 = /.*bbb/g;
        var re2 = /.*?bbb/g;
        var re3 = /.*+bbb/g;

        //1. 贪婪性量词的匹配过程:

        re1.test("abbbaabbbaaabbb1234");// false- no match
        re1.test("abbbaabbbaaabbb123");// false- no match
        re1.test("abbbaabbbaaabbb12");// false- no match
        re1.test("abbbaabbbaaabbb1");// false- no match
        re1.test("abbbaabbbaaabbb");// true-  match

        //2. 惰性量词的匹配过程
        
        re2.test("a");//false - no match
        re2.test("ab");//false - no match
        re2.test("abb");//false - no match
        re2.test("abbb");//true - match

        //store this result and start with next letter

        re2.test("a");//false - no match
        re2.test("aa");//false - no match
        re2.test("aab");//false - no match
        re2.test("aabb");//false - no match
        re2.test("aabbb");//true - match

        //store this result and start with next letter

        re2.test("a");//false - no match
        re2.test("aa");//false - no match
        re2.test("aaa");//false - no match
        re2.test("aaab");//false - no match
        re2.test("aaabb");//false - no match
        re2.test("aaabbb");//true - match

        //store this result and start with next letter

        re2.test("1");//false - no match
        re2.test("12");//false - no match
        re2.test("123");//false - no match
        re2.test("1234");//false - no match

        //3. 支配性量词匹配过程

        re3.test("abbbaabbbaaabbb1234");//false - no match

        /**
         * 注意:浏览器对支配性量词的支持还很不完善,IE和Opera不支持支配性量词,
         * 如果要用它,就会抛出一个错误。Mozilla不会产生错误,但是它会将支配性量词看作贪婪的。
         * **/


      /**
       * 正则表达式高级进阶(复杂模式)
       * **/

       /*
        1. 分组:
          分组是通过一系列括号包围一系列字符,字符类以及量词来使用。
       */

       var reDogDog = /dogdog/g;
       //使用分组表示:
       var reDogDog = /(dog){2}/g;
       //分组后面接量词:
       var reDogDog = /(dog)?/g;//零次或一次
       var reDogDog = /(dog)*/g;//零次或多次(任意次)
       var reDogDog = /(dog)+/g;//一次或多次(至少一次)


       //匹配头部和尾部空白的正则表达式:
       //以任意次的空格开头中间有任意个字符,然后再以至少一个空格字符结尾
        var reExtraSpace = /^s*(.*?)s+$/;
        var str = "  hhhdhhhd";
        var str1 = "  hhhdhhhd ";
        var str2 = "hhhdhhhd ";
        reExtraSpace.test(str);//false
        reExtraSpace.test(str1);//true
        reExtraSpace.test(str2);//true

        /**
         * 2. 反向引用
         *  每个分组都被存放在一个特殊的地方以备将来使用。
         *  这些存储在分组的特殊值,我们称之为反向引用。
         *  反向引用是按照从左到右遇到的左括号字符的顺序进行创建和编号的。
         * 例如:表达式(A?(B?(c?)))
         * **/
          //(1) (A?(B?(c?)))
          //(2) (B?(c?))
          //(3) (c?)
          
        /**
         *  反向引用的使用方法
         *  1.使用正则表达式对象的test()/match()或search()方法后,
         *  反向引用的值可以从RegExp构造函数中获得。
         * 例如:
         * **/
        var sToMatch = "#123456789";
        var reNumbers = /#(d+)/;
        reNumbers.test(sToMatch)
        console.log(RegExp.$1);//123456789

        //调换字符串中两个单词的顺序
        var sToChange = "1234 5678";
        var reMatch = /(d{4}) (d{4})/;
        var sNew = sToChange.replace(reMatch, "$2 $1");// "5678 1234" 

        /**
         * 3. 边界
         *  ^   行开头
         *  $   行结尾
         *    单词的边界
         *  B  非单词的边界
         *
         * **/

         //1. 假设想查找一个单词,但要它只出现在行尾,则可以使用美元符合$来表示它:
         var sToMatch = "Imporant word is the last one.";
         var reLastWord = /(w+).$/;
         reLastWord.test(sToMatch);
         console.log(RegExp.$1);//one
        

         //2.查找第一个单词
         var sToMatch = "Imporant word is the last one.";
         var reFirstWord = /^(w+)/;
         reFirstWord.test(sToMatch);
         console.log(RegExp.$1);//Imporant

         //3. 如果遇到非单词符,匹配停止
         var sToMatch = "Imporant word is the last one.";
         var reFirstWord = /^(.+?)/;
         reFirstWord.test(sToMatch);
         console.log(RegExp.$1);//Imporant

         //4. 使用单词边界可以很方便地从字符串中抽取单词:

         var sToMatch = "Imporant word is the last one";
         var reWords = /(S+?)/g;
         reWords.match(sToMatch);//["Imporant", "word", "is", "the", "last", "one"]

  //4.理解RegExp对象
    /**
     * 1. 实例属性
     *  global----------Boolean值,表示g(全局选项)是否已设置
     *  ignoreCase------Boolean值,表示i(忽略大小写选项)是否已设置
     *  lastIndex-------整数,代表下次匹配将会从哪个字符位置开始(只有当使用exec()或test()函数才会填入,否则为0)。
     *  multiline-------Boolean值,表示m(多行模式选项)是否已设置
     *  source----------正则表达式的源字符串形式。例如:表达式 /[ba]*/ //的source将返回"[ba]*" 
原文地址:https://www.cnblogs.com/pylf/p/14132166.html