正则:使用特殊符号字母数字建立一个规则,用于提取符合规则的字符串。
任何编程语言都有相应的正则表达式API,比如python的re,本文主要讨论javascript中的正则
定义正则表达式
- 字面量---双斜杠
let pattern = /s$/
- 构造函数RegExp()
let pattern = new RegExp("s$", 'g')
正则表达式的一般规则
1. 字符类
把个别字面值字符放到方括号中可以组合成字符类
| 字符 | 匹配目标 | ||
|---|---|---|---|
| [...] | 方括号中的任意一个字符 | ||
| [^...] | 不在方括号中的任意一个字符 | ||
| · | 除换行符或其他Unicode字符行终止符之外的任意字符。如果RegExp使用s标志,则句点匹配任意字符,包括行终止符 | ||
| \w | \W | 任意ASCII单词字符 [a-zA-Z0-9] | 非ASCII [^a-zA-Z0-9] |
| \s | \S | 任意Unicode空白字符 | 任意非空白字符 |
| \d | \D | 任意数字 | 任意非数字 |
| [\b] | 退格字符字面量 |
2. 重复
| 符号 | 匹配目标 |
|---|---|
| {n,m} | 匹配前项n~m次 |
| {n, } | 匹配前项至少n次 |
| {n} | 匹配前项恰好n次 |
| ? | 匹配前项0次或1次。等价于{0,1} |
| + | 匹配前项1次或多次。等价于{1,} |
| * | 匹配前项0次或多次。等价于{0,} |
上表重复字符会尽可能多的匹配,即“贪婪的”。在重复字符后面加个 ?就能指定非贪婪匹配。
aaa /a+/ ==> aaa
aaa /a+?/ ==> a
4 任选、分组和引用
| 符号 | 匹配目标 | |
|---|---|---|
| 任选:匹配左侧的子表达式或右侧的子表达式 | ||
| (...) | 分组:将模式分组为一个单元,以便使用*、+、?、 | 等。同时记住与分组匹配的字符,以便在后面的引用中使用 |
| (?:...) | 仅分组:将模式分组为一个单元,不记住与分组匹配的字符 | |
| \n | 匹配与第n个分组匹配的相同字符,分组是圆括号(可能嵌套)中的子表达式,从左到右计数,(?:...)不参与。 | |
| (?<>...) | 命名捕获组 |
5 指定匹配位置
正则表达式锚点字符
| 字符 | 匹配目标 |
|---|---|
| ^ | 匹配开头 |
| & | 匹配结尾 |
| \b | 匹配单词边界。匹配\w和\W字符之间或\w字符与字符串开头或字符串结尾之间的位置 |
| \B | 匹配非-单词边界(断句) 的位置 |
| (?=p) | 肯定式向前查找断言。要求匹配后面的字符匹配模式p,但匹配结果不包含与p匹配的字符 |
| (?!p) | 否定式向前查找断言。要求后面的字符不匹配模式p |
| (?<=p) | 肯定式向后查找断言 |
| (?<!p) | 否定式向后查找断言 |
6 标志
每个正则表达式都可以带一个或多个标志,用于修改其行为。
| 字符 | 匹配目标 |
|---|---|
| g | 全局。找到字符串中所有匹配项 |
| i | 大小写。模式匹配不区分大小写 |
| m | 多行模式。RegExp用于多行字符串,锚点^$匹配任意一行的开头和结尾 |
| s | 适用于搜索的文本含换行符。.将匹配包括行终止符在内的任意字符 |
| u | 让正则表达式匹配完整的码点而不是匹配16位值 |
| y | 粘性。在字符串开头匹配或紧跟前一个匹配的第一个自付出匹配。 |
7 模式匹配的字符串方法
// search()不支持g标志
"JavaScript".search(/script/ui) // 4
"Python".search(/script/ui) // -1
// replace()
var text = "javaScript"
text.replace(/javascript/gi, "JavaScript")
// 分组
let quote = /"([^"]*)"/
'He said "stop"'.replace(quote, '<$1>') // He said <stop>
// 命名捕获组
let quote = /"(?<qouteRes>[^"]*)"/
'He said "stop"'.replace(quote, '<$<qouteRes>>') // He said <stop>
// 函数参数
let s = '15 times 15 is 225'
const res = s.replace(/\d+/gu, n => parseInt(n).toString(16)) // f times f is e1
// match() 受g影响
"7 plus 8 equals 15".match(/\d+/g) // ['7', '8', '15']
// exec(), 会改变lastIndex
let p = /Java/g
let text = 'JavaScript > Java'
let match
while ((match = p.exec(text)) !== null) {
console.log(`matched ${match[0]} at ${match.index}`)
console.log(`Next Search begins at ${p.lastIndex}`)
}
// matched Java at 0
// Next Search begins at 4
// matched Java at 13
// Next Search begins at 17