关于正则

JavaScript 正则表达式用法整理大纲

介绍

  • 正则表达式(Regex)是一种用于匹配字符串中字符模式的工具,它可以用于搜索、替换和验证文本,例如检查邮箱格式、提取特定数据或清洗数据。正则表达式的灵活性使其在文本处理和数据分析中非常有用,它在 JavaScript 中的文本处理非常重要,因其可以高效地搜索、匹配和替换字符串。通过正则表达式,开发者可以快速找到特定模式的文本,如电子邮件地址、电话号码等,或者对文本进行复杂的替换操作。此外,正则表达式在数据清洗、格式验证和日志分析中也广泛应用,帮助简化和优化代码逻辑。

基础语法

  1. 元字符

    • .:匹配除换行符之外的任意字符。
    • \d:匹配数字。
    • \w:匹配字母、数字、下划线。
    • \s:匹配空白字符。
  2. 字符类

    • 方括号 []:匹配方括号内的任意一个字符,例如 [abc] 匹配 a、b 或 c。
    • 取反字符 ^:在方括号的开头,表示匹配不在方括号内的字符,例如 [^abc] 匹配除了 a、b、c 之外的任何字符。
  3. 数量词

    • *:匹配零个或多个前面的字符,例如 a* 匹配空字符串或多个 a。
    • +:匹配一个或多个前面的字符,例如 a+ 匹配至少一个 a。
    • ?:匹配零个或一个前面的字符,例如 a? 匹配空字符串或一个 a。
    • {n}:匹配恰好 n 个前面的字符,例如 a{3} 匹配 aaa。
    • {n,}:匹配至少 n 个前面的字符,例如 a{2,} 匹配两个或更多 a。
    • {n,m}:匹配 n 到 m 个前面的字符,例如 a{2,4} 匹配 aa、aaa 或 aaaa。
  4. 锚点

    • ^:匹配字符串的开头。
    • $:匹配字符串的结尾。
  5. 转义字符

    • 反斜杠 \:用于转义特殊字符,例如 \. 匹配字面上的点号。
  6. 分组和选择

    • 圆括号 ():用于分组,例如 (abc) 可以作为一个整体进行匹配。
    • 竖线 |:表示“或”,例如 a|b 匹配 a 或 b。
  7. 常用修饰符

    • i 修饰符:忽略大小写。
    • g 修饰符:全局匹配。
    • m 修饰符:多行匹配。

常用方法

test()方法:检测字符串是否匹配正则表达式。

在 JavaScript 的正则表达式中,test() 方法是一个用于测试一个字符串是否匹配某个正则表达式的方法。这个方法返回一个布尔值,如果字符串与正则表达式匹配,则返回 true,否则返回 false

语法:
regex.test(string);
参数:
  • regex: 要匹配的正则表达式。
  • string: 要测试的字符串。
返回值:
  • 如果字符串与正则表达式匹配,则返回 true,否则返回 false
示例:
const regex = /hello/;
const str1 = "Hello, world!";
const str2 = "Hi there!";

console.log(regex.test(str1)); // 输出: true,因为 "Hello" 在字符串中被找到
console.log(regex.test(str2)); // 输出: false,因为 "hello" 在字符串中未被找到

exec()方法:在字符串中执行正则表达式搜索,并返回匹配的结果。

在 JavaScript 的正则表达式中,exec() 方法是一个用于在字符串中执行一个搜索匹配的方法。当一个字符串与正则表达式匹配时,exec() 方法会返回一个数组,其中存储了匹配的结果。如果没有找到匹配,exec() 方法返回 null

语法:
regex.exec(string);
参数:
  • regex: 要匹配的正则表达式。
  • string: 要进行匹配的字符串。
返回值:
  • 如果匹配成功,exec() 方法返回一个数组,其中第一个元素是与整个正则表达式匹配的文本,后续元素是正则表达式中每个捕获组所匹配的文本。如果没有找到匹配,则返回 null
示例:
const regex = /l\w{2}/g;
const str = "Hello, world!";

let result;
while ((result = regex.exec(str)) !== null) {
  console.log("Found: " + result[0] + ", Index: " + result.index);
}

// 这里输出的内容是
// Found: llo, Index: 2
// Found: ld, Index: 10

高级技巧

贪婪与非贪婪匹配。

在正则表达式中,贪婪匹配和非贪婪匹配是指正则表达式在匹配过程中的两种不同的行为。这两种匹配方式会影响正则表达式匹配的行为和结果。

  1. 贪婪匹配

    • 贪婪匹配是指正则表达式尽可能多地匹配字符。
    • 当使用贪婪匹配时,正则表达式会尽可能匹配更多的字符,直到无法继续匹配为止。
    • 贪婪匹配通常在量词后面加上一个 ? 来表示非贪婪匹配。

    示例

    • /.+/ 这个正则表达式是贪婪匹配,它会匹配尽可能多的字符,直到遇到换行符为止。
  2. 非贪婪匹配(也称为懒惰匹配或最小匹配):

    • 非贪婪匹配是指正则表达式尽可能少地匹配字符。
    • 当使用非贪婪匹配时,正则表达式会尽可能匹配更少的字符,以满足匹配条件。
    • 非贪婪匹配通常在量词后面加上一个 ? 来表示非贪婪匹配。

    示例

    • /.+?/ 这个正则表达式是非贪婪匹配,它会匹配尽可能少的字符,直到满足匹配为止。
  3. 示例

    const text = "<p>Hello, <b>world</b></p>";
    
    // 贪婪匹配示例
    const greedyRegex = /<.*>/; // 贪婪匹配,匹配尽可能多的字符
    const greedyMatch = text.match(greedyRegex);
    console.log("Greedy match:", greedyMatch[0]); // 输出: "<p>Hello, <b>world</b></p>"
    
    // 非贪婪匹配示例
    const lazyRegex = /<.*?>/; // 非贪婪匹配,匹配尽可能少的字符
    const lazyMatch = text.match(lazyRegex);
    console.log("Lazy match:", lazyMatch[0]); // 输出: "<p>"
    

    在上面的示例中,我们使用了两种正则表达式。<.*> 表示贪婪匹配,它会匹配尽可能多的字符,所以整个 <p>Hello, <b>world</b></p> 被匹配了。而 <.*?> 表示非贪婪匹配,它会匹配尽可能少的字符,因此只匹配到了第一个<p>

前瞻断言和后顾断言。

在正则表达式中,前瞻断言(positive lookahead)和后顾断言(positive lookbehind)是一种零宽断言(zero-width assertions),它们用于在匹配字符串时指定必须满足但并不包含在最终匹配结果中的条件。

  1. 前瞻断言(Positive Lookahead)
  • 前瞻断言用于查找在其后跟随指定模式的位置。
  • 语法:(?=pattern)
  • 示例:/foo(?=bar)/ 匹配后面紧跟着 "bar" 的 "foo",但只匹配 "foo",不匹配 "bar"。
  1. 后顾断言(Positive Lookbehind)
  • 后顾断言用于查找在其前面紧跟指定模式的位置。
  • 语法:(?<=pattern)
  • 示例:/(?<=foo)bar/ 匹配前面紧跟着 "foo" 的 "bar",但只匹配 "bar",不匹配 "foo"。
  1. 示例 1:使用前瞻断言

    const str = "Hello, world!";
    const regex = /Hello, (?=world)/;
    
    const result = str.match(regex);
    console.log(result); // 输出: ["Hello, "]
    

    在这个示例中,正则表达式 /Hello, (?=world)/ 使用了前瞻断言,匹配后面紧跟着 "world" 的 "Hello, ",但只匹配 "Hello, ",并将结果存储在 result 中。

  2. 示例 2:使用后顾断言

    const str = "Hello, world!";
    const regex = /(?<=Hello, )world/;
    
    const result = str.match(regex);
    console.log(result); // 输出: ["world"]
    

    在这个示例中,正则表达式 /(?<=Hello, )world/ 使用了后顾断言,匹配前面紧跟着 "Hello, " 的 "world",但只匹配 "world",并将结果存储在 result 中。

替换和捕获组。

在正则表达式中,替换和捕获组是两个重要的概念,它们用于在文本处理中查找、匹配和替换特定模式的字符串。

  1. 捕获组(Capturing Groups)

    • 捕获组是用圆括号 () 包围的正则表达式部分,它用于将匹配的子字符串分组。
    • 可以通过捕获组从匹配的文本中提取所需的部分,或者在替换操作中引用捕获组中的内容。
    • 捕获组可以使用索引或名称来访问。
  2. 替换操作(Replacement)

    • 在正则表达式中,可以使用替换操作将匹配到的文本替换为指定的字符串。
    • 替换操作通常使用 replace() 方法来实现。
    • 替换操作可以包括捕获组中的内容,通过使用特殊的字符引用捕获组。
  3. 示例

    const str = "2022-10-05";
    const regex = /(\d{4})-(\d{2})-(\d{2})/;
    const result = str.replace(regex, "$2/$3/$1");
    
    console.log(result); // 输出: "10/05/2022"
    

    在这个示例中,正则表达式 (\d{4})-(\d{2})-(\d{2}) 匹配日期格式 "YYYY-MM-DD",并将年、月、日分别作为捕获组。在替换操作中,$1$2$3 分别表示第一个、第二个和第三个捕获组的内容,从而实现将日期格式转换为 "MM/DD/YYYY" 的形式。

  4. 补充示例

    const str = "apple, orange, banana";
    const newStr = str.replace(/(\w+)/g, (match, content, index, str) =>
      match.toUpperCase()
    );
    console.log(newStr); // 输出: "APPLE, ORANGE, BANANA"
    

    在这里 match 表示匹配到的字符串,content 表示捕获组中的内容,这里捕获组可以有多个,取决于正则中捕获组()的个数,其中如果是(?:pattern),则是非捕获组,str 表示原始字符串,index 表示匹配到正则表达式字符串的索引值

总结

正则表达式在 JavaScript 中非常重要且灵活。它们强大地支持模式匹配,可用于字符串操作和文本处理。正则表达式具有灵活性和可扩展性,能够优化性能并提高效率。通过将常用表达式封装,可以实现表达式的复用和维护,使代码更简洁、可读性更强。