js正则基础概念

#### 正则表达式字符表示列表 ####
    **\** : 将下一个字符标记为一个特殊字符、或一个原以字符、或一个向后引用、或一个八进制转义符。例如
    "n"匹配字符"n"。"\n"匹配一个换行符。序列"\\"匹配"\",而"\("则匹配"("。
    **^** : 匹配字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配"\n"或"\r"之后的位置
    **$** : 匹配字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配"\n"或"\r"之前的位置
    ** * **:匹配前面的子表达式零次或多次。例如,"zo*"能匹配"z"以及"zoo"。*等价于{0,};
    **+** : 匹配前面的表达式至少一次。例如,"zo+"能匹配"zo"以及"zoo"。等价于{1,};
    **?** : 匹配前面的表达式0次或1次。例如,"do(es)?"可以匹配"do"或"does"中的"do"。?等价于{0,1};
    **{n}** : n是一个非负整数。匹配确定的n次。
    **{n,}** : n是一个非负整数。至少匹配n次。
    **{n,m}** : m和n均为非负整数,其中n<m。最少匹配n次且最多匹配m次。
    **?** : 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪模式的。
    非贪婪模式尽可能少的匹配所搜索的字符串。例如,对于字符串"oooo","o+"将匹配所有"o",
    "o+?"将匹配单个"o";
    **.** : 匹配除"\n"之外的任何单个字符。要匹配包括"\n"在内的任何字符,请使用像"[.\n]"的模式。
    **(pattern)** : 匹配pattern并获取这一匹配。所获取的匹配可以从产生Matches集合得到,
    在VBScript中使用SubMatches集合,在jscript中则使用$0...$9属性。要匹配圆括号字符,请使用"\("或"\)"。
    **(?:pattern)** : 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。
    例如"indust(?y:ies)"就是一个比"industy|industies"更简略的表达式;
    **(?=pattern)** : 正向预查,在任何匹配pattern的字符串开始出匹配查找字符串。
    这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?95|98|nt|2000)"能匹配
    "Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,
    在匹配发生后,在最后一次匹配之后立即开始下一次匹配搜索,而不是从包预查的字符之后开始。
    **(?!pattern)** : 负向预查。"Windows(?!95|97|nt|2000)",能匹配"Windows3.5"中的Windows,
    不能匹配"Windows2000"中的"Windows"。
    **x|y** : 匹配x或者y
    **[xyz]** : 字符集合。匹配所含的任何一个字符。例如,"[abc]"可以匹配"plain"中的"a";
    **[^xyz]** : 负值字符集合。匹配未包含的任意字符。例如,"[^abc]"可以匹配"plain"中的"p";
    **[a-z]** : 字符范围
    **\b** : 匹配一个单词边界,也就是指单词和空格间的位置。例如:"er\b"可以匹配"never"中的"er",
    但不能匹配"verb"中的"er"。
    **\B** : 匹配非单词边界。"er\B"能匹配"verb"中的"er",但不能匹配"never"中的"er"
    **\cx** : 匹配由x指明的控制字符。例如:\cM匹配一个Control-M或回车键。x的值必须为A-Z或者a-z之一。
    否则,将c视为一个原以的"c"字符
    **\d** : 匹配一个数字字符。等价于[0-9]
    **\D** : 匹配一个非数字字符。等价于[^0-9]
    **\f** : 匹配一个换页符。等价于\x0c和\cL
    **\n** : 匹配一个换行符。等价于\x0a和\cJ
    **\r** : 匹配一个回车符。等价于\x0d和\cM
    **\s** : 匹配任何空白字符,包括空格、制表符、换页符等。等价于[\f\n\r\t\v]
    **\S** : 匹配任何非空格符。等价于[^\f\n\r\t\v]
    **\t** : 匹配一个制表符。等价于\x09和\cI
    **\v** : 匹配一个垂直制表符。等价于\x0b和\cK
    **\w** : 匹配包括下划线的任何单词字符。等价于"[A-Za-z0-9_]"
    **\W** : 匹配任何非单词字符。等价于"[^A-Za-z0-9_]"
    **\Xn** : 匹配n,其中n为16进制转义值。十六进制转义值必须为确定的两个数字长。例如,"\x41"匹配"A"。
    "\x041"则等价于"\x04&1"。正则表达式中可以使用ASCII编码。
    **\num** : 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,"(.)\1"匹配两个连续的相同字符。
    **\n** : 标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。
    否则,如果n为八进制数字(0-7),则n为一个八进制转义值
    **\nm** : 标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。
    如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,
    若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm
    **\nml** : 如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml
    **\Un** : 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(?)
#### 正则表达式的常用匹配 ####
    1.匹配非负整数(正整树数 + 0):^\d+$
    2.匹配正整数 : ^[0-9]*[1-9][0-9]*$\
    3.匹配非正整数(负整数 + 0) : ^((-\d+)|(0+))$
    4.匹配负整数 : ^-[0-9]*[1-9][0-9]*$
    5.匹配整数 : ^-?\d+$
    6.匹配非负浮点数(正浮点数 + 0) : ^\d+(\.\d+)?$
    7.匹配正浮点数 : ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
    8.匹配非正浮点数(负浮点数 + 0) : ^((-\d+(\.\d+)?)|(0+(\.0+)?))$
    9.匹配负浮点数 : ^(-(([0-9]+\.[0-9]*[0-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]*[1-9][0-9]*)))$
    10.匹配浮点数 : ^(-?\d+)(\.\d+)?$
    11.匹配由26个英文字符组成的字符串 : ^[A-Za-z]+$
    12.匹配由26个英文字母及数字组成的字符串 : ^[A-Za-z0-9]+$
    13.匹配由数字、26个英文字母或下划线组成的字符串 : ^\w+$
    14.匹配中文字符的正则表达式 : [\u4e00-\u9fa5]
    15.匹配双字节字符(包括汉字在内) : [^\x00-\xff]
    16.匹配空行的正则表达式 : \n[\s| ]*\r
    17.匹配HTML标记的正则表达式 : /<(.*)>.*<\/\l>|<(.*)\/>/
    18.匹配首尾空格的正则表达式 : (^\s*)|(\s*$)
    19.中国身份证号:(^d{15}$)|(\d{17}(?:\d\x\X)$)
    20.邮箱 : ^[0-9a-zA-Z]+@(([0-9a-zA-Z]+)[.])+[a-z]{2,4}$
    21.手机号 : ^(1(([35][0-9])|(47)|[8][01236789]))\d{8}$
    22.手机号电话号同时验证 : (^\(?\d{3,4}[\)\-]?\d{5,10}$)|(^\[1358]d[10]$)
    23.实现手机号前带86或+86的情况 : ^((\+86)|(86))?(13)\d{9}$
    24.电话号码手机号码同时验证 : (^(\d{3,4}-)?\d{7,8})$|(13[0-9]{9})
    25.网络链接 : (h\H)(r|R)(e|E)(f|F) *= *('|")?(\w|\\|\.)+('|"\ *|>)?
    26.图片链接 : (s|S)(r|R)(c|C) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?\
    27.中国电话号码(包括移动和固定电话) : (\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}
    28.中国固定电话号码 : (\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}
    29.中国邮政编码 : [1-9]{1}(\d+){5} 
    30.ip地址 : ^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9])\.(25[0-5]|2[0-4][0-9]|
    [0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|
    [1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$
    31.简单的日期判断(yyyy/mm/dd) : ^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$
    32.演化的日期判断(yyyy/mm/dd|yy/mm/dd) : ^(^(\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2}$)|
    (^\d{4}年\d{1,2}月\d{1,2}日$)$
    33.匹配网址URL的正则表达式 : ((http|ftp|https|file):\/\/([\w\-]+
    (\/[\w\u4e00-\u9fa5\-\.\.\/?\@\%\!\&=\+\~\:\#\;\,]*)?)
#### js匹配正则(test,exec,match,search,replace,split) ####
    1.test  检查指定的字符串是否存在
        var data = "123123";
        var reCat = /123/gi;
        alert(reCat.test(data));//检查字符是否存在 g 继续往下走 i 不区分大小写
    2.exec 返回查询值
        var data = "123,12,32,Cat,cat";
        var reCat = /cat/i;
        alert(reCat.exec(data));//Cat
    3.match 得到查询数组
        var data = "123123,213,3,231,Cat,cat";
        var reCat = /cat/gi;
        var arrMatches = data.match(reCat);
        for(var i=0,len=arrMatches;i<len;i++){
            alert(arrMatches[i]);//Cat cat
        }
    4.search 返回搜索位置 类似indexof
        var data = "123123,234,4231,Cat,cat";
        var reCat = /cat/gi;
        alert(data.search(reCat));//18
    5.replace 替换字符 利用正则替换
        var data = "123123,21,342,Cat,cat";
        var reCat = /cat/gi;
        alert(data.replace(reCat,"lili"));
    6.split 利用正则分割数组
        var data = "123213,1232,32,21,321,Cat,cat";
        var reCat = /\,/;
        var arrdata = data.split(reCat);
        for(var i=0,len=arrdata.length;i<len;i++){
            alert(arrdata[i]);
        }
#### 简单类,负向类,范围类,组合类 ####
    //简单类
        var data = "1l,2l,3l";
        var reCat = /[123]l/gi;
        var arrdata = data.match(reCat);
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);//1l 2l 3l
        }
    //负向类
        var data = "al,1l,2l,3l,4l";
        var reCat = /[^a123]l/gi;
        var arrdata = data.match(reCat);
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);//4l
        }
    //范围类
        var data = "l1,l2,l3,l4";
        var reCat = /l[2-3]/gi;
        var arrdata = data.match(reCat);
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);//l2 l3
        }
    //组合类
        var data = "a,b,c,w,1,2,3,5";//\u0062cf
        var reCat = /[a-q1-4\n]/gi;
        var arrdata = data.match(reCat);
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);//a b c 1 2 3
        }
#### js 正则表达式分组知识 ####
    1.简单分组
        //ex:查找字符串 MouseMouse
        var data = "Ah-mousemouse";
        var reCat = /Mouse{2}/gi;
        var arrdata = data.match(reCat);//得到查询数组
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);//mousemouse
        }
    2.复杂分组
        var data = "bb ba da bad aa";
        var reCat = /([bd]ad?)/gi;
        var arrdata = data.match(reCat);
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);//ba da bad dad
        }//注意?的使用,0次或一次
    3.反向引用
        var sTomatch = "#123456789";
        var reNumbers = /#(\d+)/;
        reNumber.test(reNumbers);
        alert(RegExp.$1);//123456789
        //这个例子尝试匹配后面跟着几个或数字的#符号,并对数字进行分组以保存。在调用
        test方法后,所有的反向引用都保存到了RegExp构造函数中从RegExp.$1开始,如果还有第二个反向引用,
        就是RegExp.$2,以此类推。因为该数组匹配了"123456780",所以RegExp中就存储了这个字符串。
        var sToChange = "1234 5678";
        var reMatch = /(\d{4} \d{4})/;
        var sNew = sToChange.replace(rematch,"$1","$2");
        alert(sNew);//5678 1234  分组匹配
    4.候选
        var sToMatch1 = "red";
        var sToMatch2 = "black";
        var reRedOrBlack = /(red|black)/;
        alert(reRedOrBlack.test(sToMatch1));//true
        alert(reRedOrBlack.test(sToMatch2));//true
    5.非捕获性分组
        //如果要创建一个非捕获分组,只要在括号的后面加上一个问号和一个紧跟的冒号
        var sToMatch = "#123456789";
        var reNumbers = /#(?:\d+)/;
        reNumbers.test(sToMatch);
        alert(RegExp.$1);//这个例子的最后一行输出一个空字符串,因为该组是非捕获的
        var sToMatch = "#123456789";
        var reNumbers = /#(?:\d+)/;
        alert(sToMatch.replace(reNumbers,"abcd$1"));
        //正因为此,replace()方法就不能通过RegExp.$X变量来使用任何反向引用,这段代码输出的
        "abcd$1"而不是八成多23456789,因为在这里并不被看成是一个反向引用。
    6.前瞻:告诉正则表达式运算器向前看一些字符而不是移动位置
        var sToMatch1 = "bedroom";
        var sToMatch2 = "bedding";
        var reBed1 = /bed(?=room)/;
        var reBed2 = /bed(?!room)/;
        alert(reBed1.test(sToMatch1));//true
        alert(reBed2.test(sToMatch1));//false
    7.边界
        var sToMatch = "important word is the last one.";
        var reLastWord = /(\w+)\.$/;
        relastWord.test(sToMatch);
        alert(RegExp.$1);//one
            //假如想查找一个单词,但要它只出现在行尾,则可以使用美元符号表示它;
        var sToMatch = "important word is the last one.";
        var reLastWord = /^(\w+)/;
        reLastWord.test(sToMatch);
        alert(RegExp.$1);//important
            //查找其实位置的一个或多个单词字符。遇到非单词字符则停止
        var sToMatch = "important word is the last one.";
        var reLastWord = /^(.+?)\b/   //不包含\n  单词边界
        reLastWord.test(sToMatch);
        alert(RegExp.$1);//important
            //这里,正则表达式用惰性量词来制定在单词边界之前可以出现任何字符,
            且可以出现一次或多次(如果使用贪婪性量词,表达式就匹配整个字符串)
        var data = "first second thind fourth fifth sixth ";
        var reCat = /\b(\S+?)\b/g;
        var arrdata = data.match(reCat);
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);
        }//抽取单词
    8.多行模式
        var data = "first second thind fourth\n fifth sixth";
        var reCat = /(\w+)$/gm;
        var arrdata = data.match(reCat);
        for(var i=0;i<arrdata.length;i++){
            alert(arrdata[i]);//fourth sixth
        } 
#### 方法介绍 ####
    1.regexp.exec(string)
        exec方法是使用正则表达式最强大(最慢)的方法。如果它成功匹配了string,会返回一个数组,
        数组下标为0的元素将包含正则表达式regexp匹配的子字符串,下标1的元素是分组1捕获的文本...,
        以此类推,除了数组元素和length之外,exec还返回两个属性,index声明的是匹配文本的第一个
        字符的位置,input属性则存放的是被检索的字符串。如果匹配失败,会返回null。在调用非全局的
        regexp对象的exec方法时,返回的数组与调用方法string.match返回的数组是相同的。如果exep
        带有一个g表示,事情会变得复杂,查找不是从这个字符的其实位置开始,而是从regexp.lastIndex
        (初始值为0)位置开始。如果匹配成功,那么regexp.lastIndex将被设置为该匹配后的最后一个字符
        的位置。这就意味着可以反复调用exec()来获得字符串中所有匹配文本,当再也找不到匹配的文本时,
        它将返回null,并会重置regexp.lastIndex为0通过循环调用exec去查询一个匹配模式在一个字符串
        中发生了几次,1.如果提前退出循环,再次进入循环前必须把regexp.lastIndex重置为0;
    2,^因子仅匹配regexp.lastIndex为0的情况。
            ex:
                var str = "visit bobo bobo";
                var patt = /bobo/g;
                var result;
                console.log("带有g标识的循环调用");
                while ((result = patt.exec(str) )! = null){
                    console.log(result);//第一次输出["bobo",index:6,input:"visit bobo bobo"],
                                        //第二次输出["bobo",index:11,input:"visit bobo bobo"]
                    //下一个匹配位置
                    console.log(patt.lastIndex);//第一次输出10,第二次输出15
                }
                console.log("非手动退出循环式regexp.lastIndex的值");
                console.log(patt.lastIndex);//0
    
                console.log("不带g标示的exec");
                var patt1 = /bobo/;
                var result = patt1.exec(str);
                console.log(patt1.lastIndex);//不带标识的时候,每一次exec执行完毕,lastIndex都重置为0
                console.log(result);//["bobo",index:6,input:"visit bobo bobo"];
    2.regexp.test(string)
        test方法是使用正则表达式最简单(最快)的方法,如果匹配返回true,否则返回false。r.rest(string)等同于
        r.exec(string) != null.不要对这个方法运用g标示
    3.string.match(regexp)
        match方法让一个字符串和一个正则表达式匹配。依据g标示来决定如何进行匹配。
        如果没有g标识,那么string.match(regexp)的结果与调用r.exec(string)的结果相同。仅仅执行一次匹配,如果
        没有找到 任何匹配的文本,就返回null,否则返回一个数据,数组的第0个是匹配的文本,下标为1对应着捕获组1捕获
        的文本,...一次类推。此外,结果还具有index和input属性。分别代表匹配开始的下标的输入的文本。
        如果带有g标识,那么它执行全局检索,生成一个包含所有匹配(此时会将分组忽略,当成普通的正则处理)的数组;
        若没有找到任何匹配的元素则返回null。全局匹配返回数组的内容与前者大不相同,数组中存放的是string的所有
        匹配子串,也没有index属性和input属性。
        ex:
            //测试不带g标示的match方法
            var reg = /bobo(leishao)/;
            var str = "boboleishao leishaobobo boboleishao";
            var result = str.match(reg);
            console.log(result);//["boboleishao","leishao",index:0,input:str];
            console.log(reg.lastIndex);//0
            //测试带g标识的match方法
            var reg1 = /bobo(leishao)/g;
            var str1 = "boboleishao leishaobobo boboleishao";
            var result1 = str1.match(reg1);
            console.log(result);//["boboleishao",'boboleishao']
            console.log(reg1.lastIndex);//0
            //在jQuery中使用这种方法,将一个或多个空格分开的字符串切割成一个数组
            var rnotwhite = /\S+/g;
            var teststr = "bobo leishao bobo";
            console.log(teststr.match(rnowhite));//["bobo","leishao","bobo"]
    4.string.replace(searchValue,replaceValue)
        string.replace方法对string进行查找和替换操作,并返回一个新的字符串。
        searchValue 1.如果是字符串,那么只会在第一次出现的时候替换;2.如果是一个正则表示式,
        并且带有g标识,那么它会替换所有的匹配,如果没有g标识,它仅替换首个匹配。
        a.如果replaceValue一个字符串,字符串$具有特殊含义
            $$替换$;
            $&替换整个匹配的文本;
            $number匹配捕获的分组;
            $匹配之前的文本
            $'匹配之后的文本
        b.如果replace是一个函数,那么每遇到一次匹配都会调用一次,函数的返回值将会作为替换文本,
        传递给函数的第一个参数是整个被匹配的文本,第二个参数是分组1捕获的文本,以此类推...并且数组最后
        有两个参数,一个匹配开始的位置,一个参数是输入文本
            ex:
                //测试replace文本
                var str = "leisaho bobo leishao";
                //不含有g标识的正则
                console.log(str.replace(/leishao/,"shaoxianlei"));//"shaoxianlei bobo leishao"
                //含有g标识的正则
                console.log(str.replace(/leishao/g,"shao"));//"shao bobo shao";
                //$的特殊意义
                console.log(str.replace(/(\w+)\s+(\w+)/,"$2 $1"));//bobo leishao leishao
                //测试第二个参数是函数
                var str = "leishao bobo leishao bobo";
                console.log(str.replace(/(\w+)\s+(\w+)/,function(all,str1,str2){
                    console.log(all);//leisho bobo
                    console.log(str1);//leishao
                    console.log(str2);//bobo
                    return all.toUpperCase();//LEISHAO BOBO leishao bobo
                    }));
                    //如果是带有g标识,并且第二个参数是函数
                    console.log(str.replace(/(\w+)\s+(\w+)/g,function(all,str1,str2){
                        console.log(all);//调用两次,两次都输出leishao bobo
                        console.log(str1);//调用两次,都输出leishao
                        console.log(str2);//调用两次,都输出bobo
                        console.log(arguments);//调用两次,第一次输出["leishao bobo","leishao","bobo",0,"leishao bobo leishao bobo"];
                        第二次输出["leishao bobo","leishao","bobo",13,"leishao bobo leishao
                     bobo"]
                        return all.toUpperCase();//LEISHAO BOBO LEISHAO BOBO
                    }));
                    console.log("没有分组的情况");
                    //如果正则中没有分组,第二个参数是函数
                    console.log(str.replace(\/\w+\s+\w+/g,function(all,str1,str2){
                        console.log(all);调用两次
                        console.log(arguments);//调用两次,第一次输出["leishao bobo",0,"leishao bobo leishao bobo"];第二次输入["leishao bobo",13,"leishao bobo leishao bobo"]
                        return all.toUpperCase();
                    })) ;
    5.string.split(seperator,limit)
        该方法用于将一个字符串分割为字符串数组。seperator必须,为字符串或正则,当是正则表达式时,该方
    法或略g标识,
        limit可选,该参数可以指定返回数组的最大长度
        a.如果seperator是空字符串,那么返回一个单字符的数据
        b.如果是正则表达式,会忽略g标识;如果正则表达式包含分组,那么分组捕获的文本会包含在分割后的数
    组中
            1.如果seperator是空字符串
            var digits = "12345";
            console.log(str.split(""));//["1","2","3","4","5"]
            var str = "a|b|c|";
            console.log(str.split("|"));/["a","b","c",""];
            var text = "last, first,middle";
            console.log(str.split(/\s*,\s*/));//["last","first","middle"]
            //需要注意的是,来自分组的文本会被包含在被分割的数组中
            console.log(text.split(/\s*(,)\s*/));//["last",",","first",",","middle"]
    6.sting.search(regexp)
        search方法用于检索字符串中指定的子字符串,或者检索与正则表达式相匹配的子字符串,如果检测不到,
    返回-1
            1.参数regexp可以是子字符串,这时候感觉使用IndexOf更方便一些
            2.regexp可以是正则表达式对象,这时候会忽略g标识;如果要执行忽略大小写的检索,可以加上i标
        识
            var regexp = /\w+\s*,\s*\w+/i;
            console.log("bobo leishao ,bobo".search(regexp));//5

posted @ 2017-03-16 16:35  Ruuudy  阅读(236)  评论(0)    收藏  举报