正则表达式的flag标识
正则表达式具有可选的flag,这些flag可以单独使用,也可以任意组合使用,不分顺序。flag可选值见下表:
| flag | 描述 | 对应属性名 |
|---|---|---|
d | 生成 | hasIndices |
g | 全局搜索 | global |
i | 大小写不敏感(不区分大小写) | ignoreCase |
m | 允许^和$匹配新行(多行搜索) | multiline |
s | 允许.匹配新行字符串(匹配换行符) | dotAll |
u | Unicode 将一个匹配视为 Unicode 序列(Unicode 码) | unicode |
y | 搜索类型变为sticky,从目标字符串的当前位置开始匹配 | sticky |
字符串的match(regexp)方法
match(regexp)语法
regexp 正则表达式
return 一个数组 Array
- 当
regexp存在g标识时,会返回所有匹配到的字符串; - 当
regexp不存在g标识时,会返回带有index, input, groups属性的数组,与正则表达式的exec方法返回值一致。
示例 match
该示例中,正则表达式存在 g标识,会返回所有匹配到的字符串;
let str01 = 'The simplest approach will prove to be the most effective',
str03 = '最简单的方法往往是最有效的'
/** g 全局搜索 */
let reg01 = /The/g
/** i 不区分大小写 */
let reg02 = new RegExp('the', 'ig')
let reg03 = /的/g
let arr01 = str01.match(reg01)
let arr02 = str01.match(reg02)
let arr03 = str03.match(reg03)
console.log(arr01); // [ 'The' ]
console.log(arr02); // [ 'The', 'the' ]
console.log(arr03); // [ '的', '的' ]
character classes 字符类
字符类用于区分不同类型的字符
| 字符 | 含义 |
|---|---|
[xyz] [a-c] | 匹配 [ 中括号里面的任意一个字符 ],可以使用 - 来指定字符的范围。例如 [a-c] 匹配 a、b、c 任意一字符。 |
[^xyz] [^a-c] | 匹配任意一个不包含在 [] 里面的字符 |
. | 任意一个除了行终止符以外的字符,行终止符主要有:\n, \r |
\d | 任意一个阿拉伯数字,即 [0-9] |
\D | 任意一个非数字字符,即 0-9 |
\w | 字母数字下划线,即 [a-zA-Z0-9_] |
\W | 非字母数字下划线,即 a-za-z0-9_ |
\s | 空白字符,包括空格,Tab,制表符,行终止符 |
\S | 非空白符 |
\t | tab 键水平制表符(水平缩进) |
\r | 回车符 |
\n | 换行符 |
\v | 垂直制表符 |
\f | 制页符 |
[\b] | 退格符(backspace)(注意 \b 是单词边界) |
\0 | NULL |
\cX | 当 X 为 [A-Z] 时,匹配脱字符 caret notation |
\xhh | 使用两个 16 进制数值(hh)匹配字符 |
\uhhhh | 使用 4 个 16 进制数值(hhhh)匹配 UTF-16 字符 |
\u{hhhh}或\u{hhhhh} | 当使用 flags 属性为 u 时,使用 16 进制数值匹配字符 |
\p{UnicodeProperty}, \P{UnicodeProperty} | 基于 UnicodeProperty 匹配字符,比如中文、日文、表情等(配合 flag:u 使用) |
\ | 转义符,意味着后面的一位字符特殊对待。通产而言有两种情况: 1. 将普通字面量转为特殊字符:\d 不再匹配 d,而是匹配数字; 2. 将特殊字符转为普通字面量:\. 不再匹配任意一个除了行终止符以外的字符,而是匹配 . |
x|y | x或者y; 与 [xy] 相比,使用或运算 | 可以匹配多个字符连接而成的单词,比如 red|green (注意这里运算符|前后不需要空格,如果有空格,空格也会参与匹配)表示匹配red或green |
示例 字符类
该示例中,正则表达式存在 g标识,会返回所有匹配到的字符串;
const str40 = 'username: 天涯路儿, uid: 279656749, from: bilibili, fans: 67'
/** 匹配单词开头 a-f 中的任一字符 */
const reg40 = /\b[a-f]/g
/** 匹配两个连在一起的数字 */
const reg41 = /\d\d/g
/** 匹配非空白符, (注意这里有个,) */
const reg42 = /\S,/g
/** 匹配数字字母下划线, (注意这里有个,) */
const reg43 = /\w,/g
/** 匹配中文 */
const reg44 = /[\u4e00-\u9fa5]/g
/** 匹配中文 */
const reg45 = /\p{Script=Han}/gu
/** 匹配数字 */
const reg46 = /\p{N}/gu
let res40 = str40.match(reg40)
let res41 = str40.match(reg41)
let res42 = str40.match(reg42)
let res43 = str40.match(reg43)
let res44 = str40.match(reg44)
let res45 = str40.match(reg45)
let res46 = str40.match(reg46)
console.log(res40); // [ 'f', 'b', 'f' ]
console.log(res41); // [ '27', '96', '56', '74', '67' ]
console.log(res42); // [ '儿,', '9,', 'i,' ]
console.log(res43); // [ '9,', 'i,' ]
console.log(res44); // [ '天', '涯', '路', '儿' ]
console.log(res45); // [ '天', '涯', '路', '儿' ]
console.log(res46); // [ '2', '7', '9', '6', '5', '6', '7', '4', '9', '6', '7']
Groups and backreferences捕获组和组引用
Groups将多个匹配组织为一个整体,当使用一个正则表达式去匹配一个字符串时,捕获组将提供额外的信息。
| 字符 | 含义 |
|---|---|
(x) | 匹配x并记住(捕获组)一个正则表达式中可以有多个捕获组,捕获组的顺序与左括号(的位置顺序对应;可以从匹配结果中,通过下标访问捕获元素( [0], ..., [n])或正则表达式的属性($1, ..., $n)来访问 |
(?<name>x) | 命名捕获组:尖括号<>里面写捕获组的名字 name, 将会匹配x并将x保存到groups属性中 |
(?:x) | 不捕获组:匹配但不记住 被匹配的字符串无法通过下标index ( [0], ..., [n])或正则表达式的属性($1, ..., $n)访问 |
\n | n为正整数时,引用正则表达式的第n个捕获组(即第n个小括号()里的内容) |
\k<name> | 通过名字name引用上一个命名捕获组 |
示例 使用捕获组
该例子使用()捕获组,从匹配结果中,通过下标访问捕获元素,正则表达式没有使用g标识(flag),字符串的 match 方法与正则表达式的 exec 方法的返回值一致
const str50 = `芭芭拉:节奏: S, 音准: S, 技巧: S, 感情: S, 气息: S; `
/** (\w) 捕获\w (字母数字下划线) 匹配项 */
const reg50 = /节奏: (\w), 音准: (\w), 技巧: (\w), 感情: (\w), 气息: (\w)/
const reg51 = /节奏: (\w), 音准: (\w), 技巧: (\w), 感情: (\w), 气息: (\w)/
/** 如果没有 g 标识(flag), 字符串的 match 方法与正则表达式的 exec 方法的返回值一致, 会返回带有index, input, groups属性的数组 */
let arr50 = str50.match(reg50)
let res50 = ''
console.log(arr50);
/** [
'节奏: S, 音准: S, 技巧: S, 感情: S, 气息: S',
'S',
'S',
'S',
'S',
'S',
index: 4,
input: '芭芭拉:节奏: S, 音准: S, 技巧: S, 感情: S, 气息: S; ',
groups: undefined
] */
let arr51 = reg51.exec(str50)
let res51 = ''
console.log(arr51);
/** [
'节奏: S, 音准: S, 技巧: S, 感情: S, 气息: S',
'S',
'S',
'S',
'S',
'S',
index: 4,
input: '芭芭拉:节奏: S, 音准: S, 技巧: S, 感情: S, 气息: S; ',
groups: undefined
] */
/** 通过下标 index 访问匹配结果元素, 捕获组顺序从 1 开始 */
for (let i = 0; i < 5; i++) {
res50 += arr50[i + 1] + '\t'
res51 += arr51[i + 1] + '\t'
}
console.log('节奏\t 音准\t 技巧\t 感情\t 气息\t'); // 节奏 音准 技巧 感情 气息
console.log(res50); // S S S S S
console.log(res51); // S S S S S
示例 命名捕获组
该示例中,使用了命名捕获组,捕获的字符串会保存到groups属性中
const str50 = `芭芭拉:节奏: S, 音准: S, 技巧: S, 感情: S, 气息: S; `
/** 命名捕获组, 通过 \k<level> 来引用 (?<level>\w) 中的捕获项, 即只有所有等级全为 S 时,才会匹配 */
const reg52 = /节奏: (?<level>S), 音准: (\k<level>), 技巧: (\k<level>), 感情: (\k<level>), 气息: (\k<level>)/
/** 命名捕获组 */
const reg53 = /节奏: (?<rhythm>\w), 音准: (?<intonation>\w), 技巧: (?<skill>\w), 感情: (?<emotion>\w), 气息: (?<breath>\w)/
let res52 = reg52.test(str50)
/** 命名捕获组:会将匹配项保存到 groups 属性中 */
let arr53 = str50.match(reg53)
console.log(arr53.groups);
/** [Object: null prototype] { rhythm: 'S', intonation: 'S', skill: 'S', emotion: 'S', breath: 'S'} */
let obj = arr53.groups
let res53 = ''
for (const key in obj) {
res53 += obj[key] + '\t'
}
console.log('节奏\t 音准\t 技巧\t 感情\t 气息\t'); // 节奏 音准 技巧 感情 气息
console.log(res52); // true
console.log(res53); // S S S S S