正则表达式,又叫规则表达式。把人类世界的一些字符规则以计算机可以理解的语言表达出来。Javascript提供了一个对象RegExp(Regular Expression)来管理和正则表达式相关的一切。javascript
有两种声明正则对象的方法:html
其中,attributes表明该正则的属性参数,可选值为g, i, m,分别表明全局匹配,忽略大小写,换行匹配。其中m在ECMAScript标准化以前不支持使用。前端
经常使用的正则匹配字符按功能能够分为“匹配字符”“匹配位置”和“量词”。java
字符:git
位置:正则表达式
量词:express
要想查找数字,字母或数字是很简单的,由于已经有了对应这些字符集合的元字符,可是若是你想匹配没有预约义元字符的字符集合(好比元音字母a,e,i,o,u),应该怎么办?数组
很简单,你只须要在方括号里列出它们就好了,像[aeiou]就匹配任何一个英文元音字母,[.?!]匹配标点符号(.或?或!)。前端工程师
咱们也能够轻松地指定一个字符范围,像[0-9]表明的含意与\d就是彻底一致的:一位数字;同理[a-z0-9A-Z_]也彻底等同于\w(若是只考虑英文的话)。此外,最经常使用的还有检测输入是否含有中文,使用[\u4e00-\u9fa5]。测试
字符类还能够用[^a]来匹配任何除了a之外的字符。
正则表达式里的分枝条件指的是有几种规则,若是知足其中任意一种规则都应该当成匹配,具体方法是用|把不一样的规则分隔开。
\d{5}-\d{4}|\d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之因此要给出这个例子是由于它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。若是你把它改为\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。缘由是匹配分枝条件时,将会从左到右地测试每一个条件,若是知足了某个分枝的话,就不会去再管其它的条件了。
有时须要查找不属于某个能简单定义的字符类的字符。好比想查找除了数字之外,其它任意字符都行的状况,这时须要用到反义:
若是咱们须要重复匹配多个字符,能够用小括号将须要的部分括起,指定子表达式(分组)。使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)能够在表达式或其它程序中做进一步的处理。默认状况下,每一个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。
好比咱们要匹配相似go go或kitty kitty的重复出现的字符,就可使用如下匹配方式:\b(\w+)\b\s+\1\b。
经常使用的分组语法以下:
由第二条,咱们能够获得上面正则的另外一种表现形式:\b(?<Word>\w+)\b\s+\k<Word>\b。
零宽断言用于查找在前面或后面知足某种条件的字段(但不包括先后知足匹配的那部分),也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该知足必定的条件(即断言),所以它们也被称为零宽断言。
(?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。好比\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing之外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。
(?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。好比(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re之外的部分),例如在查找reading a book时,它匹配ading。
注:JS引擎不支持这种正则表达方式。由于这种方式效率不高,推荐使用分组进行匹配。
负向零宽断言用于查找在前面或后面不知足某种条件的字段(但不包括先后知足匹配的那部分)。此处要与反义字符作区分。例如,若是咱们想查找这样的单词--它里面出现了字母q,可是q后面跟的不是字母u,咱们能够尝试这样:
\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。可是若是多作测试(或者你思惟足够敏锐,直接就观察出来了),你会发现,若是q出如今单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是由于[^u]总要匹配一个字符,因此若是q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(多是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,因而\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。负向零宽断言能解决这样的问题,由于它只匹配一个位置,并不消费任何字符。如今,咱们能够这样来解决这个问题:\b\w*q(?!u)\w*\b。
零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。例如:\d{3}(?!\d)匹配三位数字,并且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。
同理,咱们能够用(?<!exp),零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字。
这有一个用于匹配没有内联样式的HTML标签中的内容(不匹配标签):(?<=<(\w+)>).*(?=<\/\1>)。这个表达式最能表现零宽断言的真正用途。
小括号的另外一种用途是经过语法(?#comment)来包含注释。例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。
正则有一个特色——贪婪。它会匹配尽量多的东西。好比当我想将<div><bold>标题</bold>文本</div>中的标签用空格替换掉,若是使用/<.+>/则会使整段文本被替换,由于正则会匹配尽量多的字符。那么应该如何让正则匹配尽量少的字符呢?这时候就须要使用“懒惰匹配”。只须要在量词(*+[2,4])后面加一个问号,就可让正则匹配尽量少的字符。针对上面的例子就应该使用/<.+?>/。
ps: 本例也能够用/<[^<>]+>/来实现。
var str = 'abcdef'; str.search('b'); // 1 str.substring(1,4) //"bcd" str.charAt(0); //"a" var str = 'abc-12-u-qw'; var arr = str.split('-'); alert(arr); //["abc", "12", "a", "qu"]
var str = 'abc 12 as23 1'; str.search(/\d/); //4 str.match(/\d+/g); //["12", "23", "1"] str.replace(/a/g, 'T'); // 'Tbc 12 Ts23 1'
ps: replace()与正则表达式应用实例——过滤敏感词与提取HTML标签内的纯文本
在非全局匹配时,str.match(reg)和reg.exec(str)都能实现分组匹配,然而当进行全局匹配时,exec可以记录上次匹配的索引,继续进行匹配。此时一般结合循环使用,事例以下:
var s = 'aaalllsss0tAAAnnn999'; var re1 = /((\w)\2{2})(\w)\3{2}/g; var res; while(res=re1.exec(s)) { console.log("match result: " + res[1]}; console.log("re1.lastindex: " + re1.lastIndex); console.log("remain string: " + s.slice(re1.lastIndex)); }