常用
作用:找到有规则的文本
// 常用
. // 表示任意字符,不包括回车
\n // 回车
\d // 表示数字
\b // boundary 边界线,跟空格无关,而是词组的组成形式,英语是空格,中文是单字
{n} // n填数字,匹配前面的多个
\w // word,匹配字母数字或者下划线
\s // space 匹配空白符
+ // 前面的字符一个或多个
^ // 开头
$ // 结尾
$1 // 需要放在替换栏,表示匹配到的字符保存下来,$1,$2… 对应前边第n个()包裹的东西
// 嵌套时从左到右看括号
? // 可有可无 -?\d+ 表示可有负号或者可以没有
[ab] // a或b
\t //水平制表符
\v //垂直制表符
\n //换行符
\r // 回车符
\0 // 空字符
\f // 换页符
\cX // 与X对应的控制字符(Ctrl+x)
修饰符
- g : global 全局搜索
- i : ignore case 忽略大小写
- m : multiple lines 多行搜索
默认下大小写敏感,且只匹配第一个匹配到的
元字符
* + ? ^ . | \ () {} []
范围类
表示一类,其中有一个即匹配,泛指某个特征的对象
[a-z] 表示所有小写字母
[a-zA-Z] 表示所有字母
[abc] 表示abc归为一类,有其中一个
^负向类,字符类取反
[^abc] 不包含a或b或c
预定义类
字符 | 等价类 | 含义 |
---|---|---|
. | [^\r\n] | 除了回车符和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\s | [\t\n\xOB\f\r] | 空白符 space |
\S | [^\t\n\xOB\f\r] | 非空白符 |
\w | [a-zA-z_0-9] | 单词字符(字母\数字\下划线) |
\W | [^a-zA-z_0-9] | 非单词字符 |
\b | 单词边界 | |
\B | 非单词边界 | |
^ | 以xxx开始 判断依据是前面是否为空白符 | |
$ | 以xxx主动放弃 |
量词
字符 | 含义 |
---|---|
? | 出现0次或1次(最多一次) |
+ | 出现1次或者多次(至少一次) |
* | 出现0次或者多次(任意次) |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 至少出现n次 |
贪婪匹配&懒惰匹配模式
默认为贪婪模式,指有重复限定符时,匹配尽可能多的字符
限定符后使用?
则使用懒惰匹配
懒惰匹配限定符
代码/语法 | 说明 |
---|---|
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
{n,m}? | 重复n到m次,但尽可能少重复 |
{n,}? | 重复n次以上,但尽可能少重复 |
栗子
贪婪模式
'123456789'.replace(/\d{3,6}/,'x')
// 'xxxxxx789'
非贪婪模式下,会往最少的匹配
'123456789'.match(/\d{3,6}?/g)
// ['123','456','789']
捕获(分组)
// 自动命名分组
(abc){3} 使量词作用域分组
// 分组命名
(?<name>exp)
(?'name'exp) 命名为name的分组
// 不捕获(忽略分组)
(?:abc).(ok) // abc分组被忽略
// 反向引用
'2015-12-25'.replace(/(\d{4})-(\d{2})-(\d{2})/,'$2/$1/$3')
// 输出"12/25/2015"
// 引用命名
\k<name>
(?<abc>\d+)_\k<abc>\w+
// 可以在同一个正则里面用,在JavaScript RegExp对象方法.replace两个参数里也可以使用用于替换
零宽断言 (Lookahead and Lookbehind Zero-Length Assertions)
- 前瞻即匹配到规则,向前看(方向从文本末尾向开头称为前)检查是否符合断言
- 后顾/后瞻则相反
- 正向(正预测/正回顾)指条件语句匹配
- 负向相反
需注意JavaScript不支持后顾
名称 | 正则 | 含义 |
---|---|---|
正预测先行断言(正向前瞻) | assert(?=exp) | assert后面必须匹配exp条件 |
负预测先行断言(负向前瞻) | assert(?!exp) | assert后面不能匹配exp条件 |
正回顾后发断言(正向后顾) | assert(?<=exp) | JavaScript不支持 |
负回顾后发断言(负向后顾) | assert(?<!exp) | JavaScript不支持 |
JavaScript中构建方式 RegExp 对象
字面量
/\b\w/g
// 斜杠之间为正则对象 斜杠右边为修饰符
构造函数
var reg = new RegExp('\\b\\w','g')
// 两个参数 第一参数注意转义
对象属性
ignoreCase:返回一个布尔值,表示是否设置了i修饰符,该属性只读。
global:返回一个布尔值,表示是否设置了g修饰符,该属性只读。
multiline:返回一个布尔值,表示是否设置了m修饰符,该属性只读。
lastIndex:返回下一次开始搜索的位置。该属性可读写,但是只在设置了g修饰符时有意义。
source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
var reg = /abc/igm;
reg.gloabl // true 返回是否搜索全文
reg.ignoreCase // true 返回是否大小写忽略
reg.multiline // true 返回是否多行匹配
reg.lastIndex // 0 返回索引位置
reg.source // "abc" 返回正则表达式字符串形式
对象方法
RegExp.prototype.test()
返回一个布尔值,表示是否匹配
/apple/.test('牛顿吃苹果') // false
如果带g
修饰符,则每一次test()
都从上一次结束的位置开始向后匹配
var reg = /a/g
var string = "apple & apple"
reg.lastIndex // 0
reg.test(string) // true 匹配到第一个a
reg.lastIndex // 1 位置是第一个
reg.test(string) // true 匹配到第二个a
reg.lastIndex // 9 位置是第9个开始
reg.test(string) // false 匹配不到
reg.lastIndex // 0 匹配不到了
reg.test(string) // true 重新匹配到第一个
reg.lastIndex // 1 位置是第一个
RegExp.prototype.exec(str)
使用正则表达式模式对字符串进行搜索,并更新对象实例的属性,返回匹配结果。如果发现匹配,就返回一个数组,成员是每一个匹配成功的子字符串,否则返回null。
var s = 'cat'
var r1 = /a/
var r2 = /b/
r1.exec(s) // ["a"]
r2.exec(s) // null
如果正则表示式包含圆括号()
(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的length属性等于组匹配的数量再加1。
var s = '_x_x';
var r = /_(x)/;
r.exec(s) // ["_x", "x"]
上面代码的exec()
方法,返回一个数组。第一个成员是整个匹配的结果,第二个成员是圆括号匹配的结果,如果还有则继续匹配并返回到数组内
同时该数组还包含两个属性,需要注意这个与正则实例对象的属性不同
index
匹配成功的开始位置,从0开始计算
input
整个远字符串
var r = /a(p+)/
var arr = r.exec('_apple pine apple') // 是返回的数组才有属性
arr // ["app","pp"]
arr.index // 1 位置是第二个
arr.input // "_apple pine apple"
如果使用修饰符g
,下一次搜索会从上次成功匹配结束的位置开始
var r = /a(p+)/g
var s = 'apple pine pine apple pine'
var a1 = r.exec(s)
a1 //["app","pp"]
a1.index // 0
r.lastIndex // 3
var a2 = r.exec(s)
a2 //["app","pp"]
a2.index // 16
r.lastIndex // 19
// 如果匹配不到了
var a3 = r.exec(s)
a3 // null
a3.index // TypeError: Cannot read property 'index' of null
r.lastIndex // 0
// 循环了
var a4 = r.exec(s)
a4 //["app","pp"]
a4.index // 0
r.lastIndex // 3
由于其存在循环的情况,我们利用返回的数组判断循环结束,一次循环完成所有匹配
var r = /a(b+)a/g;
var s = '_abbba_aba_';
while(true) {
var match = r.exec(s);
if (!match) break; //当数组结果不存在时就跳出循环
console.log(match[1]);
}
// bbb
// b
如果设置了lastIndex
属性,就会从lastIndex
位置开始匹配,需要g
修饰符才生效
var r1 = /a(p+)/
r1.lastIndex = 5
var a1 = r1.exec('apple pine apple')
a1.index // 0
r1.lastIndex // 3
// 由于没有g 所以无效
var r2 = /a(p+)/g
r2.lastIndex = 5
var a2 = r2.exec('apple pine apple')
a2.index // 11
r2.lastIndex // 14
// 有g修饰符,所以生效
字符串对象方法 search()
| match()
| replace()
| split()
search()
返回匹配结果的在字符串中的位置,g
修饰符无效,因此lastIndex属性也无效
'apple pine apple'.search(/a(p+)/)
// 0
// 第一个位置,从0 开始数
'apple pine apple'.search(/bba/)
// -1
// 没匹配到
var r = /a(p+)/g;
r.lastIndex = 5; // 无效
'apple pine apple'.search(r) // 0
match()
返回匹配成功的的结果的数组,失败则返回null
,g
无效
var s = 'apple pine'
s.match(/a(p+)/) // ["app", "pp"]
s.match(/b(a+)/) // null
var r = /a(p+)/g
r.lastIndex = 5
s.match(r) // ["app", "pp"]
r.lastIndex // 0
// g修饰符无效
replace()
接受两个参数,第一个为搜索模式,第二个为替换内容,有g
修饰符时替换所有字符
var s = 'apple'
s.replace(/p/,'b') // "abple"
s.replace(/p/g,'b') // "abble"
// 清除字符串两端空白符
var str = ' #id div.class ';
str.replace(/^\s+|\s+$/g, '')
// "#id div.class"
replace()
方法的第二个参数可以使用美元符号$,用来指代所替换的内容
$& 指代匹配的子字符串。
$` 指代匹配结果前面的文本。
$' 指代匹配结果后面的文本。
$n 指代匹配成功的第n组内容,n是从1开始的自然数。
$$ 指代美元符号$。
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// "world hello"
'abc'.replace('b', '[$`-$&-$\']')
// "a[a-b-c]c"
第二个参数还可以是函数,将匹配内容替换为函数返回值
该函数可接受多个参数,第一个为捕捉的内容match
,第二个为第二个参数是捕捉到的组匹配(有多少个组匹配,就有多少个对应的参数)。此外,最后还可以添加两个参数,倒数第二个参数是捕捉到的内容在整个字符串中的位置(比如从第五个位置开始),最后一个参数是原字符串。
var prices = {
'pr_1': '$1.99',
'pr_2': '$9.99',
'pr_3': '$5.00'
};
var template = '/* ... */'; // 这里可以放网页模块字符串
template.replace(
/(<span id=")(.*?)(">)(<\/span>)/g,
function(match, $1, $2, $3, $4){
return $1 + $2 + $3 + prices[$2] + $4;
}
);
split()
字符串对象按正则规则分割,返回分割后组成的数组,接受两个参数,第一个为分割规则,第二个为最大成员数
// 非正则分隔
'a, b,c, d'.split(',')
// [ 'a', ' b', 'c', ' d' ]
// 正则分隔,去除多余的空格
'a, b,c, d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]
// 指定返回数组的最大成员
'a, b,c, d'.split(/, */, 2)
[ 'a', 'b' ]
// 组匹配成员也会返回到数组
'aaa*a*'.split(/(a*)/)
// [ '', 'aaa', '*', 'a', '*' ]
参考:
http://javascript.ruanyifeng.com/stdlib/regexp.html
https://regexper.com/
http://www.regular-expressions.info/lookaround.html