正则表达式
正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript 中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法,以及 String 的 match、matchAll、replace、search 和 split 方法。
创建正则表达式
使用一个正则表达式字面量,其由包含在斜杠之间的模式组成
1
var re = /ab+c/;
脚本加载后,正则表达式字面量就会被编译。当正则表达式保持不变时,使用此方法可获得更好的性能。
或者调用
RegExp对象的构造函数1
var re = new RegExp("ab+c");
在脚本运行过程中,用构造函数创建的正则表达式会被编译。如果正则表达式将会改变,或者它将会从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。
特殊字符
正则表达式中的特殊字符:
| 字符 | 含义 |
|---|---|
\ |
依照下列规则匹配:在非特殊字符之前的反斜杠表示下一个字符是特殊字符,不能按照字面理解。 |
^ |
匹配输入的开始。如果多行标志被设置为 true,那么也匹配换行符后紧跟的位置。 |
$ |
匹配输入的结束。如果多行标志被设置为 true,那么也匹配换行符前的位置。 |
* |
匹配前一个表达式 0 次或多次。等价于 {0,}。 |
+ |
匹配前面一个表达式 1 次或者多次。等价于 {1,}。 |
? |
匹配前面一个表达式 0 次或者 1 次。等价于 {0,1}。 |
.(小数点) |
默认匹配除换行符之外的任何单个字符。 |
(x) |
它会匹配 ‘x’ 并且记住匹配项。其中括号被称为捕获括号。 |
(?:x) |
匹配 ‘x’ 但是不记住匹配项。这种括号叫作非捕获括号。 |
x(?=y) |
匹配’x’仅仅当’x’后面跟着’y’.这种叫做先行断言。 |
(?<=y)x |
匹配’x’仅当’x’前面是’y’.这种叫做后行断言。 |
x(?!y) |
仅仅当’x’后面不跟着’y’时匹配’x’,这被称为正向否定查找。 |
x|y |
匹配‘x’或者‘y’。 |
{n} |
n 是一个正整数,匹配了前面一个字符刚好出现了 n 次。 |
{n,} |
n 是一个正整数,匹配前一个字符至少出现了 n 次。 |
{n,m} |
n 和 m 都是整数。匹配前面的字符至少 n 次,最多 m 次。如果 n 或者 m 的值是 0,这个值被忽略。 |
[xyz] |
一个字符集合。匹配方括号中的任意字符,包括转义序列。你可以使用破折号(-)来指定一个字符范围。对于点(.)和星号(*)这样的特殊符号在一个字符集中没有特殊的意义。 |
[^xyz] |
一个反向字符集。也就是说, 它匹配任何没有包含在方括号中的字符。 |
[\b] |
匹配一个退格 (U+0008)。(不要和\b混淆了。) |
\b |
匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。 |
\B |
匹配一个非单词的边界。 |
\cX |
当 X 是处于 A 到 Z 之间的字符的时候,匹配字符串中的一个控制符。 |
\d |
匹配一个数字。等价于 [0-9]。 |
\D |
匹配一个非数字字符。等价于 [^0-9]。 |
\f |
匹配一个换页符 (U+000C)。 |
\n |
匹配一个换行符 (U+000A)。 |
\r |
匹配一个回车符 (U+000D)。 |
\s |
匹配一个空白字符,包括空格、制表符、换页符和换行符。等价于 [ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。 |
\S |
匹配一个非空白字符。 |
\t |
匹配一个水平制表符 (U+0009)。 |
\v |
匹配一个垂直制表符 (U+000B)。 |
\w |
匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_]。 |
\W |
匹配一个非单字字符。等价于 [^A-Za-z0-9_]。 |
\n |
在正则表达式中,它返回最后的第 n 个子捕获匹配的子字符串 (捕获的数目以左括号计数)。 |
\0 |
匹配 NULL(U+0000)字符,不要在这后面跟其它小数,因为 \0<digits> 是一个八进制转义序列。 |
\xhh |
匹配一个两位十六进制数(\x00-\xFF)表示的字符。 |
\uhhhh |
匹配一个四位十六进制数表示的 UTF-16 代码单元。 |
\u{hhhh}或\u{hhhhh} |
(仅当设置了 u 标志时)匹配一个十六进制数表示的 Unicode 字符。 |
标志
正则表达式有六个可选参数 (flags) 允许全局和不分大小写搜索等。这些参数既可以单独使用也能以任意顺序一起使用,并且被包含在正则表达式实例中。
| 标志 | 描述 |
|---|---|
g |
全局搜索。 |
i |
不区分大小写搜索。 |
m |
多行搜索。 |
s |
允许 . 匹配换行符。 |
u |
使用 unicode 码的模式进行匹配。 |
y |
执行“粘性 (sticky)”搜索,匹配从目标字符串的当前位置开始。 |
用法:
1 | var re = /\w+\s/g |
如果使用 m 标志,^和$匹配的开始或结束输入字符串中的每一行,而不是整个字符串的开始或结束。
使用正则表达式
正则表达式可以被用于 RegExp 的 exec 和 test 方法,以及 String 的 match、matchAll、replace、search 和 split 方法。
| 方法 | 描述 |
|---|---|
exec |
一个在字符串中执行查找匹配的 RegExp 方法,它返回一个数组(未匹配到则返回 null)。 |
test |
一个在字符串中测试是否匹配的 RegExp 方法,它返回 true 或 false。 |
match |
一个在字符串中执行查找匹配的 String 方法,它返回一个数组,在未匹配到时会返回 null。 |
matchAll |
一个在字符串中执行查找所有匹配的 String 方法,它返回一个迭代器(iterator)。 |
search |
一个在字符串中测试匹配的 String 方法,它返回匹配到的位置索引,或者在失败时返回-1。 |
replace |
一个在字符串中执行查找匹配的 String 方法,并且使用替换字符串替换掉匹配到的子字符串。 |
split |
一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法。 |
exec
如果匹配失败,exec() 方法返回 null,并将正则表达式的 lastIndex 重置为 0。
如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的 lastIndex 属性。
1 | var myRe = new RegExp("d(b+)d", "g") |
上述代码中,匹配成功后将返回一个数组并且更新正则表达式的属性。
myArray
- 索引 0:表示最近一个匹配到的字符串。
- 大于0的索引:对应所有被记住的子字符串。
index:匹配到的字符位于原始字符串的索引值。input:初始字符串。groups:一个命名捕获组对象,其键是名称,值是捕获组。若没有定义命名捕获组,则groups的值为undefined。
myRe
lastIndex:开始下一个匹配的起始索引值。(这个属性只有在使用 g 参数时可用)
命名捕获组
1 | const date = '10-23-2022' |
命名捕获分组很大的一个作用就是它能起到注释的作用。
名捕获分组自身的语法是 (?<name>...),比普通的分组多了一个 ?<name> 字样,其中 name 的起法就和你平时起变量名一样即可(不过在这里关键字也可用)。
反向引用一个命名分组的语法是 \k<name>,注意命名分组同样可以通过数字索引来反向引用,比如:
1 | /(?<foo>a)\k<foo>\1/.test("aaa") // true |
在 replace() 方法的替换字符串中反向引用是用 $<name>:
1 | "abc".replace(/(?<foo>a)/, "$<foo>-") // "a-bc",同样 $1 仍然可用 |
总结一下就是,和命名分组相关的有三种语法,分别是 ?<name>、\k<name>、$<name>,相同点是都用尖括号包裹着分组名。
string.match
- 如果使用 g 标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。
- 如果未使用 g 标志,则仅返回第一个完整匹配及其相关的捕获组(
Array)。在这种情况下,返回的项目将具有如下所述的其他属性。
如上所述,匹配的结果包含如下所述的附加特性。
groups: 一个命名捕获组对象,其键是捕获组名称,值是捕获组,如果未定义命名捕获组,则为undefined。index: 匹配的结果的开始位置input: 搜索的字符串。
一个Array,其内容取决于 global(g)标志的存在与否,如果未找到匹配则为null。
如果正则表达式不包含 g 标志,str.match() 将返回与 RegExp.exec()相同的结果。
如果你想要获得捕获组,并且设置了全局标志,你需要用 RegExp.exec() 或者 String.prototype.matchAll()
string.matchAll
1 | str.matchAll(regexp) |
RegExp必须是设置了全局模式g的形式,否则会抛出异常TypeError。
返回值:
一个迭代器(不可重用,结果耗尽需要再次调用方法,获取一个新的迭代器)。
1 | const regexp = RegExp('foo[a-z]*','g'); |
使用括号的子字符串匹配
一个正则表达式模式使用括号,将导致相应的子匹配被记住。
下面的脚本使用 replace() 方法来转换字符串中的单词。在匹配到的替换文本中,脚本使用替代的$1 ,$2 表示第一个和第二个括号的子字符串匹配。
1 | var re = /(\w+)\s(\w+)/; |
- 本文标题:正则
- 本文作者:灵感胜于汗水
- 创建时间:2022-10-21 23:13:18
- 本文链接:https://cjhsyc.github.io/2022/10/21/正则/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!