图集1/3

正文 13565字数 186,941阅读

    正则表达式之前学习的时候,因为很久没怎么用,或者用的时候直接找网上现成的,所以都基本忘的差不多了。所以这篇文章即是笔记,也让自己再重新学习一遍正则表达式。
    其实平时在操作一些字符串的时候,用正则的机会还是挺多的,之前没怎么重视正则,这是一个错误。写完这篇文章后,发觉工作中很多地方都可以用到正则,而且用起来其实还是挺爽的。

正则表达式作用

    正则表达式,又称规则表达式,它可以通过一些设定的规则来匹配一些字符串,是一个强大的字符串匹配工具。

正则表达式方法

基本语法,正则声明

js中,正则的声明有两种方式

直接量语法:
var reg = /d+/g/
Run code
Cut to clipboard

    创建RegExp对象的语法
    var reg = new RegExp("\\d+", "g");
    Run code
    Cut to clipboard

      这两种声明方式其实还是有区别的,平时的话我比较喜欢第一种,方便一点,如果需要给正则表达式传递参数的话,那么只能用第二种创建RegExp的形式
      格式:var pattern = new RegExp('regexp','modifier');
      regexp: 匹配的模式,也就是上文指的正则规则。
      modifier: 正则实例的修饰符,可选值有:
      i : 表示区分大小写字母匹配。
      m :表示多行匹配。
      g : 表示全局匹配。

      传参的形式如下:
      我们用构造函数来生成正则表达式
      var re = new RegExp("^\\d+$","gim");
      Run code
      Cut to clipboard

        这里需要注意,反斜杠需要转义,所以,直接声明量中的语法为\d,这里需要为 \\d
        那么,给它加变量,就和我们前面写的给字符串加变量一样了。
        var v = "bl"; var re =new RegExp("^\\d+" + v + "$","gim"); // re为/^\d+bl$/gim
        Run code
        Cut to clipboard

          支持正则的STRING对象方法

          search 方法
          作用: 该方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的字符串
          基本语法: stringObject.search(regexp);
          返回值: 该字符串中第一个与regexp对象相匹配的子串的起始位置。如果没有找到任何匹配的子串,则返回-1;
          注意点: search()方法不执行全局匹配,它将忽略标志g,
          var str = "hello world,hello world"; // 返回匹配到的第一个位置(使用的regexp对象检索) console.log(str.search(/hello/)); // 0 // 没有全局的概念 总是返回匹配到的第一个位置 console.log(str.search(/hello/g)); //0 console.log(str.search(/world/)); // 6 // 如果没有检索到的话,则返回-1 console.log(str.search(/longen/)); // -1 // 我们检索的时候 可以忽略大小写来检索 var str2 = "Hello"; console.log(str2.search(/hello/i)); // 0
          Run code
          Cut to clipboard

            match()方法
            作用: 该方法用于在字符串内检索指定的值,或找到一个或者多个正则表达式的匹配。类似于indexOf()或者lastIndexOf();
            基本语法: stringObject.match(searchValue) 或者stringObject.match(regexp)
            返回值:
              存放匹配成功的数组; 它可以全局匹配模式,全局匹配的话,它返回的是一个数组。如果没有找到任何的一个匹配,那么它将返回的是null;
              返回的数组内有三个元素,第一个元素的存放的是匹配的文本,还有二个对象属性
              index属性表明的是匹配文本的起始字符在stringObject中的位置,input属性声明的是对stringObject对象的引用
            var str = "hello world"; console.log(str.match("hello")); // ["hello", index: 0, input: "hello world"] console.log(str.match("Helloy")); // null console.log(str.match(/hello/)); // ["hello", index: 0, input: "hello world"] // 全局匹配 var str2="1 plus 2 equal 3" console.log(str2.match(/\d+/g)); //["1", "2", "3"]
            Run code
            Cut to clipboard

              replace()方法
              作用: 该方法用于在字符串中使用一些字符替换另一些字符,或者替换一个与正则表达式匹配的子字符串;
              基本用法: stringObject.replace(regexp/substr,replacement);
              返回值: 返回替换后的新字符串
              注意: 字符串的stringObject的replace()方法执行的是查找和替换操作,替换的模式有2种,既可以是字符串,也可以是正则匹配模式,如果是正则匹配模式的话,那么它可以加修饰符g,代表全局替换,否则的话,它只替换第一个匹配的字符串;
                replacement 既可以是字符串,也可以是函数,如果它是字符串的话,那么匹配的将与字符串替换,replacement中的$有具体的含义,如下:
                $1,$2,$3….$99 含义是:与regexp中的第1到第99个子表达式相匹配的文本。可以看下面的例子
              $& 的含义是:与RegExp相匹配的子字符串。
                lastMatch或RegExp[“$_”]的含义是:返回任何正则表达式搜索过程中的最后匹配的字符。
                lastParen或 RegExp[“$+”]的含义是:返回任何正则表达式查找过程中最后括号的子匹配。
                leftContext或RegExp[“$`”]的含义是:返回被查找的字符串从字符串开始的位置到最后匹配之前的位置之间的字符。
                rightContext或RegExp[“$’”]的含义是:返回被搜索的字符串中从最后一个匹配位置开始到字符串结尾之间的字符。
              var str = "hello world"; // 替换字符串 var s1 = str.replace("hello","a"); console.log(s1);// a world // 使用正则替换字符串 var s2 = str.replace(/hello/,"b"); console.log(s2); // b world // 使用正则全局替换 字符串 var s3 = str.replace(/l/g,''); console.log(s3); // heo word // $1,$2 代表的是第一个和第二个子表达式相匹配的文本 // 子表达式需要使用小括号括起来,代表的含义是分组 var name = "longen,yunxi"; var s4 = name.replace(/(\w+)\s*,\s*(\w+)/,"$2 $1"); console.log(s4); // "yunxi,longen" var str = '123-mm'; var strReg = str.replace(/(\d+)-([A-Za-z]+)/g,'$2'); console.log(strReg)//mm 上面那段$2这个就是表示正则第二组个匹配到的内容,也就是说$1,$2.. 表示的是第几个括号匹配到的内容 // $& 是与RegExp相匹配的子字符串 var name = "hello I am a chinese people"; var regexp = /am/g; if(regexp.test(name)) { //返回正则表达式匹配项的字符串 console.log(RegExp['$&']); // am //返回被搜索的字符串中从最后一个匹配位置开始到字符串结尾之间的字符。 console.log(RegExp["$'"]); // a chinese people //返回被查找的字符串从字符串开始的位置到最后匹配之前的位置之间的字符。 console.log(RegExp['$`']); // hello I // 返回任何正则表达式查找过程中最后括号的子匹配。 console.log(RegExp['$+']); // 空字符串 //返回任何正则表达式搜索过程中的最后匹配的字符。 console.log(RegExp['$_']); // hello I am a chinese people } // replace 第二个参数也可以是一个function 函数 var name2 = "123sdasadsr44565dffghg987gff33234"; name2.replace(/\d+/g,function(v){ console.log(v); // 第一次打印123 // 第二次打印44565 // 第三次打印987 // 第四次打印 33234 });
              Run code
              Cut to clipboard

                REGEXP对象方法

                test()方法
                作用: 该方法用于检测一个字符串是否匹配某个模式;
                基本语法: RegExpObject.test(str);
                返回: 返回true,否则返回false;
                var str = "longen and yunxi"; console.log(/longen/.test(str)); // true console.log(/longlong/.test(str)); //false // 或者创建RegExp对象模式 var regexp = new RegExp("longen"); console.log(regexp.test(str)); // true
                Run code
                Cut to clipboard

                  exec()方法
                  作用: 该方法用于检索字符串中的正则表达式的匹配
                  基本语法: RegExpObject.exec(string)
                  返回值: 返回一个数组,存放匹配的结果,如果未找到匹配,则返回值为null;
                  注意点: 该返回的数组的第一个元素是与正则表达式相匹配的文本
                  该方法还返回2个属性,index属性声明的是匹配文本的第一个字符的位置;input属性则存放的是被检索的字符串string;该方法如果不是全局的话,返回的数组与match()方法返回的数组是相同的。
                  var str = "longen and yunxi"; console.log(/longen/.exec(str)); // 打印 ["longen", index: 0, input: "longen and yunxi"] // 假如没有找到的话,则返回null console.log(/wo/.exec(str)); // null
                  Run code
                  Cut to clipboard

                    正则表达式类型

                    元字符

                    用于构建正则表达式的符号,常用的有

                    其实常用的几个可以简单记为下面的几个意思: \s : 空格 \S : 非空格 \d : 数字 \D : 非数字 \w : 字符 ( 字母 ,数字,下划线_ ) \W : 非字符例子:是否有不是数字的字符
                    Run code
                    Cut to clipboard

                      量词

                      用于限定子模式出现在正则表达式的次数。

                      注意点:
                        刚开始学习正则的时候,是比较容易混淆 ^ : 放在正则的最开始位置,就代表起始的意思,放在中括号里,表示排除的意思。也就是说,/[^a]/和/^[a]/是不一样的,前者是排除的意思,后者是代表首位
                        $:正则的最后位置,就代表结束的意思.

                      ()分组符号可以理解为,数学运算中的括号,用于计算的分组使用。[]可以理解为,只要满足括号里面其中的某种条件即可。比如[abc],意思是满足abc中的某一个,这样比较好记。

                      贪婪模式和非贪婪模式

                      其实可以简单的理解,贪婪模式就是尽可能多的匹配,非贪婪模式就是尽可能少的匹配.
                      贪婪模式量词: {x,y} , {x,} , ? , * , 和 +
                      非贪婪模式量词: {x,y}?,{x,}?,??,*?,和 +?,所以非贪婪模式就是在贪婪模式后面加了一个问号

                      我们用代码来理解一下贪婪模式和非贪婪模式的区别
                      var str = "<p>这是第一段文本</p>text1<p>这是第二段文本</p>text2<p>xxx</p>text2again<p>end</p>"; // 非贪婪模式1 console.log(str.match(/<p>.*?<\/p>text2/)[0]); // <p>这是第一段文本</p>text1<p>这是第二段文本</p>text2 // 贪婪模式 console.log(str.match(/<p>.*<\/p>text2/)[0]); // <p>这是第一段文本</p>text1<p>这是第二段文本</p>text2<p>xxx</p>text2
                      Run code
                      Cut to clipboard

                        从上面的代码中,我们可以看到,非贪婪模式,当它匹配到它需要的第一个满足条件之后,他就会停止了。而贪婪模式则会继续向右边进行匹配下去。
                        注意点:?号在一些量词后面才是指非贪婪模式,如果直接在一些字符串的后面,表示的是匹配0次或1次。如下所示
                        var str = 'abced'; console.log(str.match(/ce?/g)); // ["ce"] console.log(reg.match(/cf?/g)); // ["c"]
                        Run code
                        Cut to clipboard

                          零宽正向断言和负向断言

                          (?=)零宽正向断言: 括号内表示某个位置右边必须和=右边匹配上
                          (?!)负向断言: 括号内表示某个位置右边不和!后的字符匹配。
                          概念很抽象,直接看代码:
                          var pattern=/str(?=ings)ing/; // 表示匹配 r 后面必须有ings的 string字符 console.log("strings.a".match(pattern)); //["string", index: 0, input: "strings.a"] // 同理,匹配string后面必须有s的 string 字符串 console.log("strings.a".match(/string(?=s)/)); //["string", index: 0, input: "strings.a"] console.log("string_x".match(pattern)); // null console.log("string_x".match(/string(?=s)/)); // null
                          Run code
                          Cut to clipboard

                            如果理解了(?=),那么(?!)就很好理解了
                            var pattern=/string(?!s)/; // 匹配string后面不带s的string字符串 console.log("strings".match(pattern)); //null console.log("string.".match(pattern)); //["string", index: 0, input: "string."]
                            Run code
                            Cut to clipboard

                              正则表达式实战练习

                              上面讲的基本都是理论,下面我们来实战一番,以此来巩固我们正则表达式的学习,学习的过程以demo的形式,对我们的知识点进行巩固。
                              下面的实例是参考这篇文章,有兴趣可以看原文,不过我整理了一下,个人觉得,把下面的例子都实践一遍,那么就基本掌握正则的使用了,满足平时的工作基本够了。

                              demo1:
                              要求:匹配结尾的数字,例如:取出字符串最后一组数字,如:30CACDVB0040 取出40
                              分析:匹配数组字符为\d,匹配1次或多次为 +,以什么结尾为 $,全局匹配为 g
                              结果:
                              console.log('30CACDVB0040'.match(/\d+$/g)); // ["0040"]
                              Run code
                              Cut to clipboard

                                如果我们只想要最后结尾的最后两个数字,则可以使用量词 {n,m},所以结果为:
                                console.log('30CACDVB0040'.match(/\d{1,2}$/g)); // ["40"]
                                Run code
                                Cut to clipboard

                                  demo2:
                                  要求:统一空格个数,例如:字符串内字符键有空格,但是空格的数量可能不一致,通过正则将空格的个数统一变为一个。
                                  分析: 匹配空格的字符为 \s
                                  结果:
                                  var str ='学 习 正 则'; console.log(str.replace(/\s+/g,' ')); // 学 习 正 则
                                  Run code
                                  Cut to clipboard

                                    demo3:
                                    要求:判断字符串是不是由数字组成
                                    分析:我们可以这样匹配,以数字 \d 开头^,以数字结尾 $,匹配零次或多次 *
                                    结果:
                                    var str ='学 习 正 则'; console.log(/^\d*$/g.test('123789')); // true console.log(/^\d*$/g.test('12378b9')); // false
                                    Run code
                                    Cut to clipboard

                                      demo4:
                                      要求:验证是否为手机号
                                      分析:现在手机开头的范围比较多,第一位是【1】开头,第二位则则有【3,4,5,7,8】,第三位则是【0-9】并且匹配9个数字。
                                      结果:
                                      var reg = /^1[3|4|5|7|8][0-9]{9}$/; //验证规则 console.log(reg.test(15984591578)); //true console.log(reg.test(11984591578)); //false
                                      Run code
                                      Cut to clipboard

                                        demo5:
                                        要求:删除字符串两端的空格
                                        分析:跟demo2类似,匹配空格 ^\s开头,空格结尾 \s$
                                        结果:
                                        var str = ' 学习正则 '; console.log(str.replace(/^\s+|\s+$/,'')); // 学习正则
                                        Run code
                                        Cut to clipboard

                                          demo6:
                                          要求:只能输入数字和小数点
                                          分析:开头需要匹配为数字,结尾也应为数字,然后再加个点,点必须转义,匹配0次或一次
                                          结果:
                                          var reg =/^\d*\.?\d{0,2}$/; console.log(reg.test('125.1')); // true console.log(reg.test('125a')); // false
                                          Run code
                                          Cut to clipboard

                                            demo7:
                                            要求:只能输入小写的英文字母和小数点,和冒号,正反斜杠(:./)
                                            分析:这几个要求组成一个分组,把他们放在一个分组里,点,正反斜杠,冒号需要转义
                                            结果:
                                            var reg = /[a-z\.\/\\:]+/; console.log('79abncdc.ab123'.match(reg)); // ["abncdc.ab", index: 2, input: "79abncdc.ab123"]
                                            Run code
                                            Cut to clipboard

                                              demo8:
                                              要求:去掉所有的html标签
                                              分析:html标签的形式为

                                              ,所以我们可以匹配<开始,然后一些内容,再加上结束符 >
                                              结果:
                                              var reg = /<[^>]+>/gi; var str = '<ul><li>hello world</li></ul>'; console.log(str.replace(reg,'')); // hello world
                                              Run code
                                              Cut to clipboard

                                                demo9:
                                                要求:绝对路径变相对路径
                                                分析: 比如: <img src="http://m.163.com/images/163.gif" /> 替换成 <img src="/images/163.gif" />.
                                                我们要替换http:// 和后面的域名,第一个 / 为止,
                                                结果:
                                                var reg = /http:\/\/[^\/]+/g; var str = 'http://m.163.com/images/163.gif'; console.log(str.replace(reg,'')); // /images/163.gif
                                                Run code
                                                Cut to clipboard

                                                  demo10:
                                                  要求:用于用户名注册,户名只能用中文、英文、数字、下划线、4-16个字符。
                                                  分析: 匹配中文的正则为 /[\u4E00-\u9FA5\uf900-\ufa2d]/,英文,数字的元字符为 \w,量词 {4,16}
                                                  结果:
                                                  var reg = /^/[\u4E00-\u9FA5\uf900-\ufa2d\w]{4,16}$/; var str1 = 'hellow_1230'; var str2 = 'hellow_1230*'; var str3 = 'hellow_12304549764654657456465756'; console.log(reg.test(str1)); // true console.log(reg.test(str2)); //false console.log(reg.test(str3)); // false
                                                  Run code
                                                  Cut to clipboard

                                                    demo11 :
                                                    要求:匹配身份证号
                                                    分析:身份证为15为或者18位,最后一位为数字或者x
                                                    结果:
                                                    var reg = /^(\d{14}|\d{17})(\d|[xX])$/; var str = '44162119920547892X'; console.log(reg.test(str)); // true
                                                    Run code
                                                    Cut to clipboard

                                                      demo12:
                                                      要求:验证邮箱
                                                      分析:邮箱的形式可能为 234564@qq.com; fasdfja@163.com,可以看到,前面为字母或者数字,然后加@,@后面可能是数字或者是其他,然后再加 . 再然后是一些com或者其他字符,我们用()来进行分组;
                                                      结果:
                                                      var reg = /^([\w_-])+@([\w_-])+([\.\w_-])+/; var str1 = 'test@hotmail.com'; var str2 = 'test@sima.vip.com'; var str3 = 'te-st@qq.com.cn'; var str4 = 'te_st@sima.vip.com'; var str5 = 'te.._st@sima.vip.com'; console.log(reg.test(str1)); // true console.log(reg.test(str2)); // true console.log(reg.test(str3)); // true console.log(reg.test(str4)); // true console.log(reg.test(str5)); // false
                                                      Run code
                                                      Cut to clipboard

                                                        demo13:
                                                        要求:匹配源代码中的链接
                                                        分析:a标签中有href,也可能有class ,id等其他属性,而且不确定a标签后面是否有空格,所以要考虑的东西比较多。
                                                        结果:
                                                        var reg = /<a\s(\s*\w*?\s*=\s*".+?")*(\s*href\s*=\s*".+?")(\s*\w*?\s*=\s*".+?")*\s*>[\s\S]*?<\/a>/g; var str = '<p>测试链接:<a id = "test" href="http://bbs.blueidea.com" title="无敌">经典论坛</a></p>'; console.log(str.match(reg)); // ["<a id = "test" href="http://bbs.blueidea.com" title="无敌">经典论坛</a>"]
                                                        Run code
                                                        Cut to clipboard

                                                          demo14:
                                                          要求:匹配a标签里面的内容
                                                          分析:上面的demo中,我们匹配到了a标签,这里的话我们匹配a标签里面的内容,这里要学习一个符号?:表示不匹配,所以我们在前面的括号中加上?:去掉a标签的匹配,然后再a标签内容里加个括号,表示分组。
                                                          结果:
                                                          var reg =/<a\s(?:\s*\w*?\s*=\s*".+?")*(?:\s*href\s*=\s*".+?")(?:\s*\w*?\s*=\s*".+?")*\s*>([\s\S]*?)<\/a>/;; var str = '<a id = "test" href="http://bbs.blueidea.com" title="无敌">经典论坛</a>'; console.log(str.replace(reg,'$1')); // 经典论坛 $1 表示的是括号里面的分组,由于前面的括号都是不获取,所以获取的第一个括号的内容就是a标签里面的内容
                                                          Run code
                                                          Cut to clipboard

                                                            demo15:
                                                            要求:获取url的指定参数的值
                                                            分析: url带参数类似为这样:http://www.baicu.com?type=1&value=789; 所以,要获取的参数要么是在?或者&开头,到下一个&或者直接后面什么都不跟为止。这里我们用new RegExp的形式,因为这样可以传参。
                                                            结果:
                                                            // 获取url中的value值 var url = 'http://www.baicu.com?type=1&value=789'; var reg = new RegExp("(^|&|\\?)value=([^&]*)(&|$)"); console.log(url.match(reg)); //["&value=789", "&", "789", "", index: 27, input: "http://www.baicu.com?type=1&value=789"] }
                                                            Run code
                                                            Cut to clipboard

                                                              稍微改编一下,我们就可以弄一个获取指定参数值的函数了
                                                              function getUrlParam(name) { var reg = new RegExp("(^|&|\\?)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) return decodeURIComponent(r[2]); return null; }
                                                              Run code
                                                              Cut to clipboard

                                                                demo16:
                                                                要求:将数字 15476465转变为15,476,465
                                                                分析:我们可以这样,匹配一个数字,然后它的后面紧跟着三个数字,并且结尾也是要有三个数字,比如 12345689我们找到 12 345 689,符合条件的是数字2和5,因为它后面紧跟着三个数字,并且这样结尾也是三个数字。然后我们在2和5的后面加个,,就达到了我们的目的12,345,689;
                                                                知识补充:这里我们需要介绍正则的一个知识点,断言?=,它只匹配一个位置。假如匹配一个“人”字,但是你只想匹配中国人的人字,不想匹配法国人的人(?=中国)人;
                                                                结果:
                                                                var str = '15476465'; var reg =/(\d)(?=(\d{3})+$)/g; console.log(str.replace(reg,'$1,')); //15,476,465
                                                                Run code
                                                                Cut to clipboard

                                                                  进一步讲解:/(\d)(?=(\d{3})+$)/匹配的是一个数字,即(\d),
                                                                  它后面的字符串必须是三的倍数,这个表达就是(?=(\d{3})+$),且最后一次匹配以 3 个数字结尾
                                                                  $1,表示在第一个分组表达式匹配的字符后面加,,这里其实只有一个(\d),问号后面的可以看成它的定语。/(\d)(?=(\d{3})+$)/g
                                                                  这个表达式通俗来说是:要找到所有的单个字符,这些字符的后面跟随的字符的个数必须是3的倍数,并在符合条件的单个字符后面添加,

                                                                  demo17:
                                                                  要求:将阿拉伯数字替换为中文大写形式
                                                                  分析:我们可以用replace来弄这个,replace中的function可以获取到匹配的每一个内容,比如返回匹配数字188,那么就会依次返回1,8,8
                                                                  结果:
                                                                  var reg = /\d/g; var arr=new Array("零","壹","贰","叁","肆","伍","陆","柒","捌","玖"); var str = '189454'; console.log(str.replace(reg,function(m) { return arr[m]; //壹捌玖肆伍肆 }));
                                                                  Run code
                                                                  Cut to clipboard