你的位置:首页 > Java教程

[Java教程]原生JS:RegExp对象详解


RegExp对象

本文参考MDN做的详细整理,方便大家参考[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)

RegExp 构造函数可创建一个正则表达式对象,用特定的模式匹配文本。

语法

  1. RegExp(pattern [, flags])
  2. /pattern/flags

参数

  • pattern 正则表达式文本
flags修饰符该参数可以是下面几个值的任意组合:
  • g  全局匹配
  • i  忽略大小写
  • m  让开始和结束字符(^ 和 $)工作在多行模式(也就是,^ 和 $ 可以匹配字符串中每一行的开始和结束(行是由 \n 或 \r 分割的),而不只是整个输入字符串的最开始和最末尾处。
  • u  Unicode。将模式视为Unicode码位(code points)序列。
  • y   新增,大部分浏览器暂不支持,sticky;matches only from the index indicated by the lastIndex property of this regular expression in the target string (and does not attempt to match from any later indexes). This allows the match-only-at-start capabilities of the character "^" to effectively be used at any location in a string by changing the value of the lastIndex property.

有两种方法可以创建一个正则对象:字面量和构造函数。要表示字符串,字面量形式不使用引号,而传递给构造函数的参数使用引号。下面表达式创建相同的正则表达式:

  1. /ab+c/i;
  2. new RegExp('ab+c', 'i'); //需要常规的字符转义规则
  3. new RegExp(/ab+c/, 'i'); //ES6新增允许的写法

  • 当表达式被赋值时,字面量形式提供正则表达式的编译(compilation)状态,正则对象在代码载入时(即编译时)生成,当正则表达式保持为常量时使用字面量。例如当你在循环中使用字面量构造一个正则表达式时,正则表达式不会在每一次迭代中都被重新编译(recompiled)。
  • 而正则表达式对象的构造函数,如 new RegExp('ab+c') 提供了正则表达式运行时编译(正则对象在代码运行时生成)。如果你知道正则表达式模式将会改变,或者你事先不知道什么模式,而是从另一个来源获取,如用户输入,这些情况都可以使用构造函数。
注意:不要把正则表达式字面量(或者正则表达式构造器)直接放在 while 条件表达式里(而应该先保存到一个变量)。因为循环的每次匹配条件都是一个新的正则表达式,每次迭代时 lastIndex 的属性都被重置为0,如果匹配,将会造成一个死循环。

  1. var myRe = /ab*/g;
  2. var str = 'abbcdefabh';
  3. var myArray;
  4. while ((myArray = myRe.exec(str)) !== null) {
  5. var msg = 'Found ' + myArray[0] + '. ';
  6. msg += 'Next match starts at ' + myRe.lastIndex;
  7. console.log(msg);
  8. }


正则对象生成以后,有两种使用方式:

  • 正则对象的方法:将字符串作为参数,如 regex.test(str)。
  • 字符串对象的方法:正则对象被作为参数,如 str.match(regex)。




正则表达式中的特殊字符

  • 字符类别(Character Classes)
  • 字符集合(Character Sets)
  • 边界(Boundaries)
  • 分组(grouping)与反向引用(back references)
  • 数量词(Quantifiers)

字符类别(Character Classes)

字符

含义

.

(点号,小数点)匹配任意单个字符,但是换行符除外,包括:\n \r \u2028 或 \u2029。

需要注意的是,m 多行(multiline)标志不会改变点号的表现。因此为了匹配多行中的字符集,可使用[^] (当然你不是打算用在旧版本 IE 中),它将会匹配任意字符,包括换行符。

例如,/.y/ 匹配 "yes make my day" 中的 "my" 和 "ay",但是不匹配 "yes"。

\d

匹配基本拉丁字母表(basic Latin alphabet)中的一个数字字符。等价于[0-9]。

例如,/\d/ 或 /[0-9]/ 匹配 "B2 is the suite number." 中的 '2'。 

\D

匹配任意一个不是基本拉丁字母表中数字的字符。等价于[^0-9]。

例如,/\D/ 或 /[^0-9]/ 匹配 "B2 is the suite number." 中的 'B'。

\w

匹配任意来自基本拉丁字母表中的字母数字字符,还包括下划线。等价于 [A-Za-z0-9_]。

例如,/\w/ 匹配 "apple" 中的 'a',"$5.28" 中的 '5' 和 "3D" 中的 '3'。

\W

匹配任意不是基本拉丁字母表中单词(字母数字下划线)字符的字符。等价于 [^A-Za-z0-9_]。

例如,/\W/ 或 /[^A-Za-z0-9_]/ 匹配 "50%" 中的 '%'。

\s

匹配一个空白符,包括空格、制表符、换页符、换行符和其他 Unicode 空格。

等价于 [ \f\n\r\t\v \u00a0\u1680 \u180e\u2000 \u2001\u2002 \u2003\u2004 \u2005\u2006 \u2007\u2008 \u2009\u200a \u2028\u2029 \u202f\u205f \u3000]。

例如 /\s\w*/ 匹配 "foo bar" 中的 ' bar'。

\S

匹配一个非空白符。等价于 [^ \f\n\r\t\v \u00a0\u1680 \u180e\u2000 \u2001\u2002 \u2003\u2004  \u2005\u2006 \u2007\u2008 \u2009\u200a \u2028\u2029 \u202f\u205f \u3000]。

例如,/\S\w*/ 匹配 "foo bar" 中的 'foo'。

\t

匹配一个水平制表符(tab)

\r

匹配一个回车符(carriage return)

\n

匹配一个换行符(linefeed)

\v

匹配一个垂直制表符(vertical tab)

\f

匹配一个换页符(form-feed)

[\b]

匹配一个退格符(backspace)(不要与 \b 混淆)

\0

匹配一个 NUL 字符。不要在此后面跟小数点。

\cX

X 是 A - Z 的一个字母。匹配字符串中的一个控制字符。

例如,/\cM/ 匹配字符串中的 control-M。

\xhh

匹配编码为 hh (两个十六进制数字)的字符。

\uhhhh

匹配 Unicode 值为 hhhh (四个十六进制数字)的字符。

\

对于那些通常被认为字面意义的字符来说,表示下一个字符具有特殊用处,并且不会被按照字面意义解释。

例如 /b/ 匹配字符 'b'。在 b 前面加上一个反斜杠,即使用 /\b/,则该字符变得特殊,以为这匹配一个单词边界。

对于那些通常特殊对待的字符,表示下一个字符不具有特殊用途,会被按照字面意义解释。

例如,* 是一个特殊字符,表示匹配某个字符 0 或多次,如 /a*/ 意味着 0 或多个 "a"。 为了匹配字面意义上的 * ,在它前面加上一个反斜杠,例如,/a\*/匹配 'a*'。

字符集合(Character Sets)

字符

含义

[xyz]

一个字符集合,也叫字符组。匹配集合中的任意一个字符。你可以使用连字符'-'指定一个范围。

例如,[abcd] 等价于 [a-d],匹配"brisket"中的'b'和"chop"中的'c'。

[^xyz]

一个反义或补充字符集,也叫反义字符组。也就是说,它匹配任意不在括号内的字符。你也可以通过使用连字符 '-' 指定一个范围内的字符。

例如,[^abc] 等价于 [^a-c]。 第一个匹配的是 "bacon" 中的'o' 和 "chop" 中的 'h'。

边界(Boundaries)

字符

含义

^

匹配输入/字符串的开始。如果多行(multiline)标志被设为 true,该字符也会匹配一个断行(line break)符后的开始处。

例如,/^A/ 不匹配 "an A" 中的 "A",但匹配 "An A" 中的 "A"。

$

匹配输入/字符串的结尾。如果多行(multiline)标志被设为 true,该字符也会匹配一个断行(line break)符的前的结尾处。

例如,/t$/ 不匹配 "eater" 中的 "t",但匹配 "eat" 中的 "t"。

\b

匹配一个零宽单词边界(zero-width word boundary),如一个字母与一个空格之间。 (不要和 [\b] 混淆)

例如,/\bno/ 匹配 "at noon" 中的 "no",/ly\b/ 匹配 "possibly yesterday." 中的 "ly"。

\B

匹配一个零宽非单词边界(zero-width non-word boundary),如两个字母之间或两个空格之间。

例如,/\Bon/ 匹配 "at noon" 中的 "on",/ye\B/ 匹配 "possibly yesterday." 中的 "ye"。

分组(Grouping)与反向引用(back references)

字符

含义

(x)

匹配 x 并且捕获匹配项。 这被称为捕获括号(capturing parentheses)。

例如,/(foo)/ 匹配且捕获 "foo bar." 中的 "foo"。被匹配的子字符串可以在结果数组的元素 [1], ..., [n] 中找到,或在被定义的 RegExp 对象的属性 $1, ..., $9 中找到。

捕获组(Capturing groups)有性能惩罚。如果再次访问被匹配的子字符串,最好使用非捕获括号(non-capturing parentheses),见下面。

\n

n 是一个正整数。一个反向引用(back reference),指向正则表达式中第 n 个括号(从左开始数)中匹配的子字符串。

例如,/apple(,)\sorange\1/ 匹配 "apple, orange, cherry, peach." 中的 "apple,orange,"。一个更全面的例子在该表格下面。

(?:x)

匹配 x 不会捕获匹配项。这被称为非捕获括号(non-capturing parentheses)。匹配项不能够从结果数组的元素 [1], ..., [n] 或已被定义的 RegExp 对象的属性 $1, ..., $9 再次访问到。

数量词(Quantifiers)

字符

含义

x*

匹配前面的模式 x 0 或多次。

例如,/bo*/ 匹配 "A ghost booooed" 中的 "boooo","A bird warbled" 中的 "b",但是不匹配 "A goat grunted"。

x+

匹配前面的模式 x 1 或多次。等价于 {1,}。

例如,/a+/ 匹配 "candy" 中的 "a","caaaaaaandy" 中所有的 "a"。

x*?

x+?

像上面的 * 和 + 一样匹配前面的模式 x,然而匹配是最小可能匹配。

例如,/".*?"/ 匹配 '"foo" "bar"' 中的 '"foo"',而 * 后面没有 ? 时匹配 '"foo" "bar"'。

x?

匹配前面的模式 x 0 或 1 次。

例如,/e?le?/ 匹配 "angel" 中的 "el","angle" 中的 "le"。

如果在数量词 *、+、? 或 {}, 任意一个后面紧跟该符号(?),会使数量词变为非贪婪( non-greedy) ,即匹配次数最小化。反之,默认情况下,是贪婪的(greedy),即匹配次数最大化。

在使用于向前断言(lookahead assertions)时,见该表格中 (?=)、(?!) 和 (?:) 的说明。

x(?=y)

只有当 x 后面紧跟着 y 时,才匹配 x。 例如,/Jack(?=Sprat)/ 只有在 'Jack' 后面紧跟着 'Sprat' 时,才会匹配它。/Jack(?=Sprat|Frost)/ 只有在 'Jack' 后面紧跟着 'Sprat' 或 'Frost' 时,才会匹配它。然而,'Sprat' 或 'Frost' 都不是匹配结果的一部分。

x(?!y)

只有当 x 后面不是紧跟着 y 时,才匹配 x。例如,/\d+(?!\.)/ 只有当一个数字后面没有紧跟着一个小数点时,才会匹配该数字。

/\d+(?!\.)/.exec("3.141") 匹配 141 而不是 3.141。

x|y

匹配 x 或 y

例如,/green|red/ 匹配 "green apple" 中的 ‘green',"red apple." 中的 'red'。

x{n}

n 是一个正整数。前面的模式 x 连续出现 n 次时匹配。

例如,/a{2}/ 不匹配 "candy," 中的 "a",但是匹配 "caandy," 中的两个 "a",且匹配 "caaandy." 中的前两个 "a"。

x{n,}

n 是一个正整数。前面的模式 x 连续出现至少 n 次时匹配。

例如,/a{2,}/ 不匹配 "candy" 中的 "a",但是匹配 "caandy" 和 "caaaaaaandy." 中所有的 "a"。

x{n,m}

n 和 m 为正整数。前面的模式 x 连续出现至少 n 次,至多 m 次时匹配。

例如,/a{1,3}/ 不匹配 "cndy",匹配 "candy," 中的 "a","caandy," 中的两个 "a",匹配 "caaaaaaandy" 中的前面三个 "a"。注意,当匹配 "caaaaaaandy" 时,即使原始字符串拥有更多的 "a",匹配项也是 "aaa"。



  1. ^等价于: [\t\n\v\f\r \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]
  2. ^等价于: [^\t\n\v\f\r \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]



属性

RegExp.prototype.lastIndex

是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引。

只有正则表达式使用了表示全局检索的 "g" 标志时,该属性才会起作用。此时应用下面的规则:

  • 如果 lastIndex 大于字符串的长度,则 regexp.test 和 regexp.exec 将会匹配失败,然后 lastIndex 被设置为 0。
  • 如果 lastIndex 等于字符串的长度,且该正则表达式匹配空字符串,则该正则表达式匹配从 lastIndex 开始的字符串。(then the regular expression matches input starting at lastIndex.)
  • 如果 lastIndex 等于字符串的长度,且该正则表达式不匹配空字符串 ,则该正则表达式不匹配字符串,lastIndex 被设置为 0.。
  • 否则,lastIndex 被设置为紧随最近一次成功匹配的下一个位置。

RegExp.prototype.source


返回一个当前正则表达式对象的模式文本的字符串,该字符串不会包含正则字面量两边的斜杠以及任何的标志字符。

RegExp.prototype.global

是否开启全局匹配,global 的值是布尔对象,如果使用了 "g" 标志,则返回 true;也就是匹配目标字符串中所有可能的匹配项,而不是只进行第一次匹配。它表明了正则表达式是否使用了 "g" 标志,global 是一个正则表达式实例的只读属性

RegExp.prototype.ignoreCase

在匹配字符串时是否要忽略字符的大小写。返回true或false,只读属性。表明了正则表达式是否使用了 "i" 标志

RegExp.prototype.multiline

是否开启多行模式匹配。返回true或false,只读属性。表明了正则表达式是否使用了 "m" 标志。若使用 了"m","^" 和 "$" 将会从只匹配正则字符串的开头或结尾,变为匹配字符串中任一行的开头或结尾。

RegExp.prototype.sticky 大部分浏览器还不支持

是否开启粘滞匹配。




实例方法:

RegExp.prototype.exec(str)

为指定的一段字符串str执行搜索匹配操作。它的返回值是一个数组或者 null。

  • 如果你仅仅是为了知道是否匹配,可以使用 RegExp.test() 方法,或者 String.search() 方法。
  • 如果成功匹配,exec 方法返回一个数组,并且更新正则表达式对象的属性。返回的数组包括匹配的字符串作为第一个元素,紧接着一个元素对应一个成功匹配被捕获的字符串的捕获括号
  • 如果正则模式是一个空字符串,则exec方法会匹配成功,但返回的也是空字符串。

  • 整个数组的length属性等于捕获匹配的数量再加1。
  • 如果正则表达式加上g修饰符,则可以使用多次exec方法,下一次搜索的位置从上一次匹配成功结束的位置开始。与exec方法不同,此时str.match(re)方法会一次性返回所有匹配成功的结果,且设置正则表达式的lastIndex属性,对match方法无效,匹配总是从字符串的第一个字符开始。

思考下面的例子:

  1. var re = /quick\s(brown).+?(jumps)/ig;
  2. 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

re

lastIndex

下一次匹配开始的位置

25

ignoreCase

是否使用了'i'标记使正则匹配忽略大小写

true

global

是否使用了'g'标记来进行全局的匹配.

true

multiline

是否使用了'm'标记使正则工作在多行模式(也就是,^ 和 $ 可以匹配字符串中每一行的开始和结束(行是由 \n 或 \r 分割的),而不只是整个输入字符串的最开始和最末尾处。)

false

source

正则模式的字符串

quick\s(brown).+?(jumps)



RegExp.prototype.test(str)

测试当前正则是否能匹配目标字符串,返回 true 或 false。(类似于 String.search),如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。如果正则模式是一个空字符串,则匹配所有字符串。

RegExp.prototype.toString()

返回一个字符串,其值为该正则对象的字面量形式。覆盖了Object.prototype.toString() 方法。