正则对象
正则对象用于将文本与一个模式匹配。
如何创建一个正则对象
- 字面量形式:由斜杠
/
包围。 - 构造函数:
new RegExp()
创建。
例如下面这三种都会创建相同效果的正则对象
/ab+c/i;
new RegExp('ab+c', 'i');
new RegExp(/ab+c/, 'i');
区别就是:当表达式被赋值时,字面量形式提供正则表达式的编译状态,而正则表达式对象的构造函数,如 new RegExp(‘ab+c’) 提供了正则表达式运行时编译
RegExp() 构造函数
语法:
new RegExp(pattern[, flags])
RegExp(pattern[, flags])
第一个参数 pattern 可以是字符串也可以是正则对象,第二个参数 flag 就是标志,如果第一个参数是正则对象,那么 flag 会替换掉之前的,如果第二个参数不传,那么之前的标志还会保留,可选的 flag 在下面标志搜索部分
正则对象的属性
- lastIndex
- flags
- dotAll
- global
- ignoreCase
- multiline
- source
- sticky
- unicode
lastIndex
lastIndex 是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引。
只有正则表达式使用了表示全局检索的 “g” 或者 “y” 标志时,该属性才会起作用。更改的规则如下:
- 如果 lastIndex 大于字符串的长度,则 regexp.test 和 regexp.exec 将会匹配失败,然后 lastIndex 被设置为 0。
- 如果 lastIndex 等于字符串的长度,且该正则表达式匹配空字符串,则该正则表达式匹配从 lastIndex 开始的字符串。
- 如果 lastIndex 等于字符串的长度,且该正则表达式不匹配空字符串,则该正则表达式不匹配字符串,lastIndex 被设置为 0。
- 否则,lastIndex 被设置为紧随最近一次成功匹配的下一个位置。
正则对象的方法
exec()
exec() 方法在一个指定字符串(也可以是正则对象,也就是把它当作字符串处理包括标志位)中执行一个搜索匹配。返回一个结果数组或 null。
在设置了 global
或 sticky
标志位的情况下(如 /foo/g or /foo/y),JavaScript RegExp 对象是有状态的。他们会将上次成功匹配后的位置记录在 lastIndex
属性中。使用此特性,exec()
可用来对单个字符串中的多次匹配结果进行逐条的遍历(包括捕获到的匹配),而相比之下,String.prototype.match()
只会返回匹配到的结果。
如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的 lastIndex 属性。完全匹配成功的文本将作为返回数组的第一项,从第二项起,后续每项都对应正则表达式内捕获括号里匹配成功的文本。
如果匹配失败,exec() 方法返回 null,并将 lastIndex 重置为 0 。
下面的例子展示了返回数组的属性
// Match "quick brown" followed by "jumps", ignoring characters in between
// Remember "brown" and "jumps"
// Ignore case
var re = /quick\s(brown).+?(jumps)/ig;
var result = re.exec('The Quick Brown Fox Jumps Over The Lazy Dog');
对象 | 属性/索引 | 描述 | 例子 |
---|---|---|---|
result | [0] | 匹配的全部字符串 | Quick Brown Fox Jumps |
[1], …[n ] | 括号中的分组捕获 | [1] = Brown [2] = Jumps | |
index | 匹配到的字符位于原始字符串的基于0的索引值 | 4 | |
input | 原始字符串 | The Quick Brown Fox Jumps Over The Lazy Dog |
test()
test() 方法执行一个检索,用来查看正则表达式与指定的字符串(与exec相同参数也可以是正则对象)是否匹配。返回 true 或 false。当想要知道一个模式是否存在于一个字符串中时,就可以使用 test()(类似于 String.prototype.search() 方法),差别在于test返回一个布尔值,而 search 返回索引(如果找到)或者-1(如果没找到)
正则表达式设置了全局标志,test() 的执行会改变正则表达式 lastIndex属性。
调用 String 对应的方法
[@@match]()
,[@@matchAll]()
,[@@replace]()
,[@@search]()
,[@@split]()
这几个方法内部都是会调用对应 String.prototype 上的方法,只不过是 this 和参数顺序不同,同时 RegExp 的子类也可以覆写这些方法来修改默认行为。
match()
match() 方法检索返回一个字符串匹配正则表达式的的结果。
- 语法:
str.match(regexp)
- 参数:
regexp:一个正则表达式对象。如果传入一个非正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp 。如果你没有给出任何参数并直接使用match() 方法 ,你将会得到一个包含空字符串的 Array :[""] 。
-
返回值:
- 如果使用g标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。
- 如果未使用g标志,则仅返回第一个完整匹配及其相关的捕获组(Array)。 在这种情况下,返回的项目将具有如下所述的其他属性。
-
附加属性
- groups: 一个捕获组数组 或 undefined(如果没有定义命名捕获组)。
- index: 匹配的结果的开始位置
- input: 搜索的字符串.
一个Array,其内容取决于global(g)标志的存在与否,如果未找到匹配则为null。
如果正则表达式不包含 g 标志,str.match() 将返回与 RegExp.exec(). 相同的结果。
matchAll
matchAll() 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。
- 语法:
str.match(regexp)
- 参数:
regexp:正则表达式对象。如果所传参数不是一个正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp。注意:RegExp必须是设置了全局模式g的形式,否则会抛出异常TypeError。
- 返回值:
一个迭代器(不可重用,结果耗尽需要再次调用方法,获取一个新的迭代器)。
在 matchAll 出现之前,通过在循环中调用 regexp.exec() 来获取所有匹配项信息(regexp 需使用 /g 标志),如果使用 matchAll ,就可以不必使用 while 循环加 exec 方式(且正则表达式需使用 /g 标志)。使用 matchAll 会得到一个迭代器的返回值,配合 for…of, array spread, 或者 Array.from() 可以更方便实现功能,如果没有 /g 标志,matchAll 会抛出异常,并且也不会改变 lastIndex。
serach()
search() 方法执行正则表达式和 String 对象之间的一个搜索匹配,如果匹配成功,则 search() 返回正则表达式在字符串中首次匹配项的索引;否则,返回 -1。
replace()
replace() 方法返回一个由替换值(replacement)替换部分或所有的模式(pattern)匹配项后的新字符串。模式可以是一个字符串或者一个正则表达式,替换值可以是一个字符串或者一个每次匹配都要调用的回调函数。如果pattern是字符串,则仅替换第一个匹配项,原字符串不会改变。
- 语法:
str.replace(regexp|substr, newSubStr|function)
-
参数:
- regexp (pattern):一个RegExp 对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。
- substr (pattern):一个将被 newSubStr 替换的 字符串。其被视为一整个字符串,而不是一个正则表达式。仅第一个匹配项会被替换。
- newSubStr (replacement):用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名。
- function (replacement):一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。
使用字符串作为参数,替换字符串可以插入下面的特殊变量名(在有匹配子串的情况下):
变量名 | 代表的值 |
---|---|
$$ | 插入一个 “$”。 |
$& | 插入匹配的子串。 |
$` | 插入当前匹配的子串左边的内容。 |
$’ | 插入当前匹配的子串右边的内容。 |
$n | 假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从1开始 |
指定一个函数作为参数, 函数的返回值作为替换字符串。(注意:上面提到的特殊替换参数在这里不能被使用。) 另外要注意的是,如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,每次匹配都会被调用。
下面是该函数的参数:
变量名 | 代表的值 |
---|---|
match | 匹配的子串。(对应于上述的$&。) |
p1,p2, … | 假如replace()方法的第一个参数是一个RegExp 对象,则代表第n个括号匹配的字符串。(对应于上述的$1,$2等。)例如,如果是用 /(\a+)(\b+)/ 这个来匹配,p1 就是匹配的 \a+,p2 就是匹配的 \b+。 |
offset | 匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是 ‘abcd’,匹配到的子字符串是 ‘bc’,那么这个参数将会是 1) |
string | 被匹配的原字符串。 |
NamedCaptureGroup | 命名捕获组匹配的对象 |
精确的参数个数依赖于 replace() 的第一个参数是否是一个正则表达式(RegExp)对象,以及这个正则表达式中指定了多少个括号子串,如果这个正则表达式里使用了命名捕获, 还会添加一个命名捕获的对象
split()
split() 方法使用指定的分隔符字符串将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置。
语法:
str.split([separator[, limit]])
参数:
- separator:指定表示每个拆分应发生的点的字符串。separator 可以是一个字符串或正则表达式。
- limit:一个整数,限定返回的分割片段数量。当提供此参数时,split 方法会在指定分隔符的每次出现时分割该字符串,但在限制条目已放入数组时停止。如果在达到指定限制之前达到字符串的末尾,它可能仍然包含少于限制的条目。新数组中不返回剩下的文本。
断言 Assertions
断言的组成之一是边界。对于文本、词或模式,边界可以用来表明它们的起始或终止部分,分为边界类断言与其他断言。边界类断言有 ^
, $
, \b
, \B
,其他断言有 x(?=y)
, x(?!y)
, (?<=y)x
, (?<!y)x
。
正则表达式中的特殊字符
字符 | 含义 |
---|---|
\ | 在非特殊字符之前的反斜杠表示下一个字符是特殊字符,不能按照字面理解,它将不再匹配任何字符,而是表示一个字符边界。在特殊字符之前的反斜杠表示下一个字符不是特殊字符,应该按照字面理解,也就是转义。 |
^ | 匹配输入的开始。如果多行标志被设置为 true,那么也匹配换行符后紧跟的位置。当 ‘^’ 作为第一个字符出现在一个字符集合模式时,它将会有不同的含义 |
$ | 匹配输入的结束。如果多行标志被设置为 true,那么也匹配换行符前的位置。 |
* | 匹配前一个表达式 0 次或多次。等价于 {0,}。 |
+ | 匹配前面一个表达式 1 次或者多次。等价于 {1,}。 |
? | 匹配前面一个表达式 0 次或者 1 次。等价于 {0,1}。如果紧跟在任何量词 *、 +、? 或 {} 的后面,将会使量词变为非贪婪(匹配尽量少的字符),和缺省使用的贪婪模式(匹配尽可能多的字符)正好相反。例如,对 “123abc” 使用 /\d+/ 将会匹配 “123”,而使用 /\d+?/ 则只会匹配到 “1”。 |
. | (小数点)默认匹配除换行符之外的任何单个字符。 |
(x) | 会匹配 ‘x’ 并且记住匹配项。其中括号被称为捕获括号。模式 /(foo) (bar) \1 \2/ 中的 ‘(foo)’ 和 ‘(bar)’ 匹配并记住字符串 “foo bar foo bar” 中前两个单词。模式中的 \1 和 \2 表示第一个和第二个被捕获括号匹配的子字符串,即 foo 和 bar,匹配了原字符串中的后两个单词。注意 \1、\2、…、\n 是用在正则表达式的匹配环节,在正则表达式的替换环节,则要使用像 $1、 2 、 . . . 、 2、...、 2、...、n 这样的语法 |
(?:x) | 匹配 ‘x’ 但是不记住匹配项。这种括号叫作非捕获括号,使得你能够定义与正则表达式运算符一起使用的子表达式。 |
x(?=y) | 匹配’x’仅仅当’x’后面跟着’y’.这种叫做先行断言。 |
(?<=y)x | 匹配’x’仅当’x’前面是’y’.这种叫做后行断言。 |
x(?!y) | 仅仅当’x’后面不跟着’y’时匹配’x’,这被称为正向否定查找。 |
(?<!y)x | 仅仅当’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 | 匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。注意,匹配中不包括匹配的字边界。换句话说,一个匹配的词的边界的内容的长度是0。 |
\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 | 匹配一个非空白字符。等价于 [^ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。 |
\t | 匹配一个水平制表符 (U+0009)。 |
\v | 匹配一个垂直制表符 (U+000B)。 |
\w | 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_]。 |
\W | 匹配一个非单字字符。等价于 [^A-Za-z0-9_]。 |
\n | 在正则表达式中,它返回最后的第n个子捕获匹配的子字符串(捕获的数目以左括号计数)。比如 /apple(,)\sorange\1/ 匹配"apple, orange, cherry, peach."中的’apple, orange,’ 。 |
\0 | 匹配 NULL(U+0000)字符, 不要在这后面跟其它小数,因为 \0<digits> 是一个八进制转义序列。 |
\xhh | 匹配一个两位十六进制数(\x00-\xFF)表示的字符。 |
\uhhhh | 匹配一个四位十六进制数表示的 UTF-16 代码单元。 |
\u{hhhh}或\u{hhhhh} | (仅当设置了u标志时)匹配一个十六进制数表示的 Unicode 字符。 |
标志搜索
标志 | 描述 |
---|---|
g | 全局搜索 |
i | 不区分大小写搜索 |
m | 多行搜索 |
s | 允许 . 匹配换行符 |
u | 使用unicode码的模式进行匹配 |
y | 执行“粘性(sticky)”搜索,匹配从目标字符串的当前位置开始 |
注意:m标志用于指定多行输入字符串应该被视为多个行。如果使用m标志,^和$匹配的开始或结束输入字符串中的每一行,而不是整个字符串的开始或结束。
y
标志与 g
标志
标志 y 会进行粘性(sticky
)匹配,它与全局匹配标志 g 一样会让引擎在匹配过程执行完毕后更新正则对象的lastIndex
属性的值,但是加了y之后,正则表达式就成了一个带隐藏属性(也就是lastIndex
)的表达式,必须从lastIndex
指定的位置匹配,如果不成功就结束语句。
注意:对于replace
和match
来讲,lastIndex
值始终是0
。