一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天
一、正则表达式简介
正则表达式是一种简单语言的语法规范,主要用于对字符串中的信息进行查找、替换以及提取操作。其性能优于等效的字符串运算,因此作为前端人学习正则表达式是很有必要的。
缺点:
- 不支持注释和空白,不利于理解、难以阅读
二、语法定义
(1)正则表达式字面量 正则表达式直接包裹在一对斜杠(/)之间
var reg = /a/g
正则表达式标志:
| 标志 | 含义 |
|---|---|
| G | 匹配全局 |
| I | 忽略大小写 |
| M | 匹配多行 |
(2)Reg构造器 这个构造器接受一个字符串参数,把它编译成RegExp对象并返回。多用于动态生成正则的情况下。
var reg = new RegExp('hello', 'g')
RegExp对象属性:
| 属性 | 用法 |
|---|---|
| global | 如果标志g被使用,返回true |
| ignoreCase | 如果i被使用,值为true |
| lastIndex | 下一次exec匹配开始的索引。初始值为0 |
| multiline | 如果m被使用,值为true |
| source | 正则表达式源代码文本 |
正则表达式字面量创建的RegExp对象共享一个实例。
function mkReg(){
return /a/gi
}
// 此时 x 和 y 是相同的对象
var x = mkReg()
var y = mkReg()
x.lastIndex = 10
console.log(y.lastIndex) // 10
RegExp对象方法:
- search(): 搜索第一个与之匹配的子串的起始位置,找到返回位置下标,找不到返回-1。不支持全局搜索
"javascript.search(/script/i)" // 4 - replace():返回替换后的字符串
- match(): 返回由匹配结果组成的数组,未匹配则返回null
组成元素
(1)因子
一个字符、一个由圆括号包围的组、一个字符组或一个转义序列都可以被称为一个正则表达式因子。除了控制字符和特殊字符外,所有的字符都将被按照字面处理:
\ / [ ] ( ) { } ? + * | . ^ $
如果你想匹配以上特殊的字符,需要借助转义字符:\(反斜杠)。
转义字符说明:
| 转义符 | 含义 |
|---|---|
| \f | 换页符 |
| \n | 换行符 |
| \r | 回车符 |
| \t | 制表符(tab) |
| \d | 匹配一个数字[0-9] |
| \D | 非数字[^0-9] |
| \w | 匹配一个下划线、一个数字或字符[0-9A-Z_a-z] |
| \W | [^0-9A-Z_a-z] |
| \s | 匹配任意空白符[ \t\r\n\v\f] |
重复字符(贪婪匹配)
| 字符 | 含义 |
|---|---|
| {n,m} | 匹配前一项至少n次,但不能超过m次 |
| {n,} | 匹配前一项至少n次或者更多次 |
| {n} | 匹配前一项n次 |
| ? | 匹配前一项0次或1次 |
| + | 匹配前一项1次或多次 |
| * | 匹配前一项0次或多次 |
贪婪匹配:最大可能匹配,即匹配到下一个字符不能满足匹配规则为止:?、+、*、{n,m}
非贪婪匹配:尽可能少的匹配,即只要一发现匹配就返回结果,不需要往下检查:??、+?、*?、{n,m}?
提示:
- 当你存在疑虑时,不妨给任何特殊字符都加一个\转义,使其字面化。
- 一个未被转义的 . 可以匹配除行结束符($)以外的任何字符。
- 当 lastIndex 属性值为0时,一个未转义的 ^ 将匹配该文本的开始。当指定了 m 标识时,它也能匹配行结束符。
- 一个未转义的 $ 可以匹配该文本的结束。当指定了 m 标识时,它也可以匹配行结束符。
(2)序列
一个正则表达式的序列包含一个或多个正则表达式因子。这个序列之后可以跟随数字,代表可以匹配的次数。
(3)选择 |
类似于运算符中的或运算,它尝试按顺序依次匹配正则表达式中的序列,如果有任何一项序列被匹配,则匹配结束。
var reg = /in|int/
console.log('into'.match(reg))
// Array [ "in" ]
//0: "in"
//groups: undefined
//index: 0
//input: "into"
//length: 1
该例只匹配到了in,不会匹配int。
(4)分组
对多个字符进行重复选择,我们可以使用小括号()指定要重复的子表达式,然后对这个子表达式进行重复。例如(abc)?表示0个1个abc 分组可以分为4种:
a. 捕获型
捕获组通过从左到右计算其开括号来编号
反向引用(back引用)
是指在后边的表达式中使用组的编号老引用前面的表达式中捕获的字符串。实例:
// IP 地址的匹配,简单写法如下
\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}
可以把.\d{1,3}看成一个整体,也就是把他们看成一组,再把这个组重复3次即可。表达式如下:
\d{1,3}(.\d{1,3}){3}
还有一种简单的用法,用\1这种语法代表前边的分组所匹配的内容,可以引用某组的文本内容,但不能引用正则表达式。
`var` `reg = /(\w{3}) is \1/`
`reg.test(``'kid is kid'`` ) ``// true`
`reg.test(``'dik is dik'`` ) ``// true`
`reg.test(``'kid is dik'`` ) ``// false`
`reg.test(``'dik is kid'`` ) ``// false`
<title>.*</title>
// 可以写成
<(title)>.*</\1>
b. 非捕获型
以(?)开头的组是非捕获组,不捕获文本,它不会针对组合进行计数。也就是说,如果小括号中以?开头,那么这么分组就不会捕获文本,当然也不会有组的编号。
非捕获型的意义:
因为捕获组获取额内容是被存储在内存中,供以后使用。而非捕获组不会捕获文本也不会将它匹配的内容单独分组放到内存中,更加节省内存。
它的作用就是匹配 pattern 字符
(?:a|A)123(?:b)可以匹配a123b或者A123b
预搜索
如果你想匹配xxx前不能是yyy,或者xxx后不能是yyy,那就要用到预搜索
js只支持先行预搜索,也就是xxx前面必须是yyy,或者xxx前面不能是yyy
(?=1)2 // 可以匹配12,不能匹配22
(?!1)2 // 可有匹配22,不能匹配12