2020年12月7日

模式和标志

正则表达式是模式,提供了一种强大的方法来搜索和替换文本。

在 JavaScript 中,它们可以通过 RegExp 对象使用,并且集成在字符串的方法中。

正则表达式

正则表达式(也称为“regexp”或“reg”)由一个模式和可选的标志组成。

有两种语法可以用来创建正则表达式对象。

“长”语法

regexp = new RegExp("pattern", "flags");

还有“短”语法,使用斜杠 "/"

regexp = /pattern/; // no flags
regexp = /pattern/gmi; // with flags g,m and i (to be covered soon)

斜杠 /.../ 告诉 JavaScript 我们正在创建一个正则表达式。它们在正则表达式中的作用类似于字符串中的引号。

在这两种情况下,regexp 都成为内置 RegExp 类的实例。

这两种语法之间的主要区别在于,使用斜杠 /.../ 的模式不允许插入表达式(例如,使用 ${...} 的字符串模板字面量)。它们是完全静态的。

当我们在代码编写时就知道正则表达式时,使用斜杠。这是最常见的情况。而 new RegExp 更常用于需要从动态生成的字符串“动态”创建正则表达式时。例如

let tag = prompt("What tag do you want to find?", "h2");

let regexp = new RegExp(`<${tag}>`); // same as /<h2>/ if answered "h2" in the prompt above

标志

正则表达式可能具有影响搜索的标志。

在 JavaScript 中只有 6 个标志

i
使用此标志,搜索将不区分大小写:Aa 之间没有区别(参见下面的示例)。
g
使用此标志,搜索将查找所有匹配项,不使用此标志,将只返回第一个匹配项。
m
多行模式(在章节 多行模式的锚点 ^ $,标志 "m" 中介绍)。
s
启用“dotall”模式,允许点 . 匹配换行符 \n(在章节 字符类 中介绍)。
u
启用完全 Unicode 支持。此标志启用对代理对的正确处理。有关更多信息,请参见章节 Unicode:标志 "u" 和类 \p{...}
y
“粘性”模式:在文本中的确切位置进行搜索(在章节 粘性标志 "y",在位置进行搜索 中介绍)
颜色

从这里开始,颜色方案是

  • regexp – 红色
  • 字符串(我们搜索的地方) – 蓝色
  • 结果 – 绿色

搜索:str.match

如前所述,正则表达式与字符串方法集成在一起。

方法 str.match(regexp) 在字符串 str 中查找 regexp 的所有匹配项。

它有 3 种工作模式

  1. 如果正则表达式带有 g 标志,它将返回所有匹配项的数组。

    let str = "We will, we will rock you";
    
    alert( str.match(/we/gi) ); // We,we (an array of 2 substrings that match)

    请注意,Wewe 都被找到了,因为 i 标志使正则表达式不区分大小写。

  2. 如果没有这样的标志,它只返回第一个匹配项,以数组的形式,其中完整匹配项位于索引 0 处,其他一些详细信息位于属性中。

    let str = "We will, we will rock you";
    
    let result = str.match(/we/i); // without flag g
    
    alert( result[0] );     // We (1st match)
    alert( result.length ); // 1
    
    // Details:
    alert( result.index );  // 0 (position of the match)
    alert( result.input );  // We will, we will rock you (source string)

    如果正则表达式的一部分用括号括起来,则该数组除了 0 之外可能还有其他索引。我们将在 捕获组 一章中介绍这一点。

  3. 最后,如果没有匹配项,则返回 null(无论是否有 g 标志)。

    这是一个非常重要的细微差别。如果没有匹配项,我们不会收到一个空数组,而是收到 null。忘记这一点可能会导致错误,例如:

    let matches = "JavaScript".match(/HTML/); // = null
    
    if (!matches.length) { // Error: Cannot read property 'length' of null
      alert("Error in the line above");
    }

    如果我们希望结果始终是一个数组,我们可以这样写:

    let matches = "JavaScript".match(/HTML/) || [];
    
    if (!matches.length) {
      alert("No matches"); // now it works
    }

替换:str.replace

str.replace(regexp, replacement) 方法使用 regexp 在字符串 str 中查找匹配项,并将其替换为 replacement(如果有 g 标志,则替换所有匹配项,否则只替换第一个匹配项)。

例如:

// no flag g
alert( "We will, we will".replace(/we/i, "I") ); // I will, we will

// with flag g
alert( "We will, we will".replace(/we/ig, "I") ); // I will, I will

第二个参数是 replacement 字符串。我们可以在其中使用特殊字符组合来插入匹配项的片段。

符号 替换字符串中的操作
$& 插入整个匹配项
$` 插入匹配项之前的字符串的一部分
$' 插入匹配项之后的字符串的一部分
$n 如果 n 是一个 1-2 位数字,则它插入第 n 个括号的内容,更多信息请参见 捕获组 一章。
$<name> 插入具有给定 name 的括号的内容,更多信息请参见 捕获组 一章。
$$ 插入字符 $

一个使用 $& 的示例

alert( "I love HTML".replace(/HTML/, "$& and JavaScript") ); // I love HTML and JavaScript

测试:regexp.test

regexp.test(str) 方法查找至少一个匹配项,如果找到,则返回 true,否则返回 false

let str = "I love JavaScript";
let regexp = /LOVE/i;

alert( regexp.test(str) ); // true

在本章的后面,我们将学习更多正则表达式,并通过更多示例,以及其他方法。

有关这些方法的完整信息,请参见 RegExp 和 String 的方法 文章。

摘要

  • 正则表达式由一个模式和可选的标志组成:gimusy
  • 如果没有标志和特殊符号(我们将在后面学习),正则表达式的搜索与子字符串搜索相同。
  • 方法 str.match(regexp) 用于查找匹配项:如果存在 g 标志,则查找所有匹配项,否则只查找第一个匹配项。
  • 方法 str.replace(regexp, replacement) 使用 regexp 查找匹配项,并用 replacement 替换它们:如果存在 g 标志,则替换所有匹配项,否则只替换第一个匹配项。
  • 方法 regexp.test(str) 如果存在至少一个匹配项,则返回 true,否则返回 false
教程地图

评论

在评论之前请阅读…
  • 如果您有任何改进建议,请提交 GitHub 问题或拉取请求,而不是评论。
  • 如果您不理解文章中的某些内容,请详细说明。
  • 要插入几行代码,请使用 <code> 标签,对于多行代码,请将它们用 <pre> 标签包裹,对于超过 10 行的代码,请使用沙箱(plnkrjsbincodepen…)。