返回

正则表达式的内在状态

前端

我敢肯定,我们很多人在处理正则表达式时都经历过类似的情况:我们有了一个正则表达式,它可以完美地匹配我们想要匹配的内容,但当我们在代码中实际使用它时,却得到了出乎意料的结果。这种情况经常发生在使用正则表达式进行全局匹配(即带有 g 标志)时。

正则表达式的状态

如果你不熟悉这个概念,正则表达式可以被视为具有状态的。这意味着它们不仅会匹配给定的输入,还会跟踪它们在输入中匹配的位置。这种状态存储在正则表达式的 lastIndex 属性中。

lastIndex 属性是一个可读写的整数,表示正则表达式下次匹配的起始索引。只有当正则表达式本身使用全局匹配 g 标志时,该属性才会被设置并且起作用。

lastIndex 属性如何工作

要了解 lastIndex 属性是如何工作的,让我们考虑以下正则表达式:

/foo/g

这个正则表达式将匹配字符串中的所有 "foo" 出现。当我们在字符串 "foofoofoo" 上运行此正则表达式时,会发生以下情况:

  1. 正则表达式第一次匹配字符串中的 "foo",并将其 lastIndex 属性设置为 3("foo" 的结束索引)。
  2. 正则表达式第二次匹配字符串中的 "foo",并将其 lastIndex 属性设置为 6("foo" 的结束索引)。
  3. 正则表达式第三次匹配字符串中的 "foo",并将其 lastIndex 属性设置为 9("foo" 的结束索引)。

使用 lastIndex 属性

了解 lastIndex 属性如何工作后,我们可以使用它来控制正则表达式在字符串中匹配内容的方式。例如,我们可以使用 lastIndex 属性来跳过我们已经匹配过的内容。

考虑以下代码:

const re = /foo/g;
const str = "foofoofoo";

while ((match = re.exec(str)) !== null) {
  console.log(match.index);

  // 跳过已经匹配过的内容
  re.lastIndex += match[0].length;
}

这段代码将打印以下内容:

0
3
6

如你所见,正则表达式跳过了我们已经匹配过的内容,并从下一个 "foo" 出现的地方继续匹配。

结论

正则表达式的 lastIndex 属性是一个强大的工具,可以帮助我们控制正则表达式在字符串中匹配内容的方式。通过了解如何使用 lastIndex 属性,我们可以编写更强大、更有效的正则表达式。