原文链接:https://segmentfault.com/a/1190000007602848
JS中,RegExp对象表示正则表达式,它是对字符串执行模式匹配的强大工具。
基本语法
方法1:
/pattern/attributes
方法2:
new RegExp(pattern, attributes);
两种方法中的attributes成为修饰符,可能是g,i,m三种不同的取值
g:globel,表示执行全局匹配,而非在找到第一个匹配后停止。
i:执行不区分大小写的匹配。
m:执行多行匹配。
方括号
方括号内可以包含一些列字符,可以匹配方括号内的任意字符,同时可以通过符号^来定义否定字符类。
[abc]:查找方括号种的任意一个字符
[^abc]:查找不在方括号内的任意一个字符
[0-9]:查找0-9种人一一个数字
(red | blue | green):查找小括号种的任意一项,|是或者的意思
元字符
. 查找任意的单个字符,除换行符和其他Unicode行终止符之外
\w 查找字母数字和下划线 ,等价于[a-zA-Z0-9_]
\W 查找除字母数字下划线之外的字符,等价于[^a-zA-Z0-9_]
\d 查找数字字符,等价于[0-9]
\D 查找非数字字符,等价于[^0-9]
\s 匹配任何空白字符,包括空格,制表符,换行符等等。等价于[\f\n\r\t\v]
\S 匹配任何非空白字符,等价于[^\f\n\r\t\v]
\b 查找一个单词边界,也就是指单词和空格间的位置,比如er\b可以匹配"never"中的"er",但是不能匹配"verb"中的"er"
\B 查找非单词边界,er\B能匹配"ver"中的"er",但不能匹配"never"中的"er"
\0 查找空字符("")
\n 查找换行符
\r 查找回车符
\f 查找换页符
\t 查找制表符
\v 查找垂直制表符
量词
n+ 匹配任何至少包含一个n的字符串,等价于n{1,}
n* 匹配零个或者多个n的字符串,等价于n{0,}
n? 匹配零个或者1个n的字符串,等价于n{0,1}
n{x} 匹配包含x个n的序列字符串
n{x,y} 匹配至少x个,最多y个n的字符串
n{x,} 匹配至少x个n的字符串
n$ 匹配以n结尾的字符串
^n 匹配以n开头的字符串
正则表达式中,特殊字符需要转译字符
正则表达式中,特殊字符都有它们特殊的含义,所以当我们要匹配这些特殊字符本身的时候,需要对字符进行转译,即在字符前面加上\,这些特殊字符包括:$ ^ * + . [ ? { | ( ) \
支持正则表达式的方法
RegExp对象方法:
1、test:
RegExpObject.test(str)
参数是要检测的字符串,如果匹配,该表达式返回true,否则返回false。
2、exec:
RegExpObject.exec(str)
函数将会反悔一个数组,返回字符串中所有匹配的结果。如果未找到匹配,则返回null。
支持正则表达式的string对象的方法
1、search:
stringObject.search(regexp)
返回在string中第一个可以和regexp对象匹配的字符串的起始位置,如果没有找到任何可以匹配的字符串,则返回-1.
2、match:
stringObject.match(regexp)
返回匹配成功的数组,如果没有找到匹配,则返回null。
3、replace:
stringObject.replace(regexp/substr,replacement);
该方法用于在字符串中用另一些字符替换原字符,其中,参数replacement可以是替换的文本或者是生成替换文本的函数。
如果replacement是字符串,那么匹配向将会被这个字符串代替。需要注意的是,在replacement中,$字符具有特殊的含义,利用这些,我们可以将从模式匹配得到的字符串用于替换
$1、$2、...、$99 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
$& 与 regexp 相匹配的子串。
$` 位于匹配子串左侧的文本。
$' 位于匹配子串右侧的文本。
$$ 表示美元符号$。
例子:
var name = "longen ,yunxi";
var s4 = name.replace(/(\w+)\s*,\s*(\w+)/,"$2 $1");
console.log(s4); // "yunxi,longen"
console.log('hello world'.replace(/w/g, '$&')) //hello world
console.log('hello world'.replace(/w/g, '$$')) //hello $orld
console.log('hello world'.replace(/w/g, '$`')) //hello hello orld
console.log('hello world'.replace(/w/g, "$'")) //hello orldorld
另外,如果regexp具有全局标志,那么replace方法会将所有匹配的字符串替换,否则,只替换第一个匹配子串。
4、split
stringObject.split(separator,howmany)
其中,参数:
1.separator[必填],字符串或正则表达式,该参数指定的地方分割stringObject;
2.howmany[可选] 该参数指定返回的数组的最大长度,如果设置了该参数,返回的子字符串不会多于这个参数指定的数组。如果没有设置该参数的话,整个字符串都会被分割,不考虑他的长度。
返回值:一个字符串数组。该数组通过在separator指定的边界处将字符串stringObject分割成子字符串。
贪婪模式与非贪婪模式
贪婪模式在整个表达式匹配成功的情况下尽可能多的匹配,非贪婪模式则在整个表达式匹配成功的前提下,尽可能少的匹配。
一些常见的修饰贪婪模式的量词:
{x,y},{x,},?,*和+
非贪婪模式就是在贪婪模式的量词后加一个?
{x,y}?,{x,}?,??,*?,和+?
例子:
//贪婪模式,尽可能多的匹配
console.log('0123456789'.replace(/\d{3,6}/,"*")) //*6789
//非贪婪模式,尽可能少的匹配
console.log('0123456789'.replace(/\d{3,6}?/,"*")) //*3456789
分组
//不分组,量词仅作用到最后一个字符(c)
console.log(/abc{2}/.test('abcabc')); // false
console.log(/abc{2}/.test('abcc')); //true
//分组,量词作用于整个括号里的子表达式
console.log(/(abc){2}/.test('abcabc')); // true
console.log(/(abc){2}/.test('abcc')); //false
反向引用
当一个正则表达式被分组后,每一个分组将会自动被赋予一个组号,从左到右依次为:$1 $2 …
//格式化日期
var reg = /^(\d{4})[/-](\d{2})[/-](\d{2})$/
console.log('2016/11/18'.replace(reg, '$1年$2月$3日')) //2016年11月18日
console.log('2016-11-18'.replace(reg, '$1年$2月$3日')) //2016年11月18日
console.log('2016-11-18'.replace(reg, '$1$2$3')) //20161118
非捕获性分组
不是所有的分组都能创建反向引用,有一种分组叫做非捕获性分组,非捕获性分组用(?:pattern)表示,一些只需要分组匹配,但是并不需要得到各个分组匹配的结果时,使用非捕获性分组可以提高匹配速度。
非捕获分组的含义我们可以理解为如下:子表达式可以作为被整体修饰但是子表达式匹配的结果不会被存储;如下:
var reg = /(?:\d{4})-(\d{2})-(\d{2})/
var date = '2012-12-21'
reg.test(date)
RegExp.$1 // 12
RegExp.$2 // 21
这里,(?:d{4})分组不会捕获任何字符串,所以$1为(d{2})捕获的字符串。
零宽断言
零宽断言就是下结论,例如字符串是ab,正则表达式为:a(?=b),匹配a并且a的右边是b,得到的结果是a,断言不会在匹配的内容当中,如果是a(?=c),则匹配不到任何内容,因为匹配a以后向右看并不是c。另外,零宽断言分两种:前瞻(Lookahead)和后顾(Lookbehind);但JavaScript只支持前瞻。
前瞻表达式的语法如下:
m(?=n) 匹配后面紧接n的字符串m
m(?!n) 匹配后面没有紧接n的字符串m