深入解析-正则表达式

学习正则,我们到底要学什么?

正则表达式(RegEx)是一种强大的文本匹配工具,广泛应用于数据验证、文本搜索、替换和解析等领域。学习正则表达式,我们不仅要掌握其语法规则,还需要学会如何高效地利用正则来解决实际问题,避免复杂的模式导致性能问题。

核心目标

  • 理解正则表达式的基本构成与工作原理。
  • 熟悉常见的正则元字符、量词、分组等基本构成要素。
  • 掌握如何高效地构建正则表达式来处理各种文本问题。

1. 元字符:如何巧妙记忆正则表达式的基本元件?

正则表达式的基本构成是元字符,它们代表了字符的匹配规则。常见的元字符包括:

  • .:匹配任意字符(除了换行符)
  • \d:匹配任何数字字符(0-9)
  • \w:匹配字母、数字及下划线(a-zA-Z0-9_)
  • \s:匹配任何空白字符(如空格、制表符、换行符)
  • []:定义一个字符集,匹配字符集中的任意一个字符。

示例:

java 复制代码
// 示例:匹配任意一个数字
String regex = "\\d";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher("a3b");
while (matcher.find()) {
    System.out.println("找到数字: " + matcher.group());
}

输出:

复制代码
找到数字: 3

记忆技巧

  • . 就像一个万能的"通配符"。
  • \d 对应数字,\w 对应字母和数字。
  • [] 是字符集,用来指定一组匹配条件。

2. 量词与贪婪:小小的正则,也可能把 CPU 拖垮!

量词用于指定某个元素出现的次数。常见的量词包括:

  • *:表示前面的元素可以重复零次或多次(贪婪模式)。
  • +:表示前面的元素至少出现一次。
  • ?:表示前面的元素出现零次或一次。

示例:

java 复制代码
// 贪婪模式:匹配多个字符
String regex = "a.*b";  // 贪婪模式,匹配从 'a' 到 'b' 之间的所有字符
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher("a1b2c3b");
while (matcher.find()) {
    System.out.println("匹配到: " + matcher.group());
}

输出:

复制代码
匹配到: a1b2c3b

贪婪模式会尽可能多地匹配字符,可能导致性能问题。为避免这种情况,可以使用非贪婪模式(*?, +?)。

java 复制代码
// 非贪婪模式:匹配最小的字符集
String regex = "a.*?b";  // 非贪婪模式,匹配最短的 'a' 到 'b' 之间的字符
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher("a1b2c3b");
while (matcher.find()) {
    System.out.println("匹配到: " + matcher.group());
}

输出:

复制代码
匹配到: a1b

3. 分组与引用:如何实现更复杂的查找替换操作?

分组用于将正则表达式中的部分内容封装在括号中,这样我们就可以对匹配的部分进行引用或者替换。

示例:

java 复制代码
// 使用分组进行文本替换
String regex = "(\\d+)-(\\d+)";
String replacement = "$2-$1";  // 引用第二个分组和第一个分组
String input = "123-456";
String output = input.replaceAll(regex, replacement);
System.out.println(output);  // 输出: 456-123

解释(\\d+)-(\\d+) 会匹配由数字组成的两个部分并用 () 分组。在替换中,$1$2 分别代表第一个和第二个分组。

4. 匹配模式:带你一次性掌握常见的 4 种匹配模式

常见的四种匹配模式包括:

  • 默认模式:按行匹配。
  • Pattern.CASE_INSENSITIVE:忽略大小写。
  • Pattern.DOTALL. 可以匹配换行符。
  • Pattern.MULTILINE^$ 可以匹配行的开头和结尾。

示例:

java 复制代码
String regex = "^[a-z]+$";
String input = "hello";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(input);
System.out.println(matcher.matches());  // 输出: true

解释 :该正则表达式匹配的是由小写字母组成的整个字符串,使用 Pattern.CASE_INSENSITIVE 忽略大小写。


5. 断言:如何用位置匹配更好地实现替换重复单词?

断言(Assertions)是正则表达式中一种特殊的工具,用于根据位置或条件进行匹配。断言分为两种:

  • 正向断言(?=...) 用来匹配某个位置后满足条件的字符串。
  • 负向断言(?!...) 用来匹配某个位置后不满足条件的字符串。

应用场景

  • 用于避免重复单词的匹配,或者仅在某个条件满足时进行匹配。

示例:

java 复制代码
// 去除重复单词,使用正向断言
String regex = "\\b(\\w+)\\b(?=.*?\\b\\1\\b)";
String input = "hello world hello java world java";
String output = input.replaceAll(regex, "");
System.out.println(output);  // 输出: "world java"

解释

  • \\b:单词边界,确保匹配的是完整的单词。
  • (\\w+):匹配一个或多个字母数字字符,并将其捕获为组1。
  • (?=.*?\\b\\1\\b):正向断言,确保后面还有该单词出现。

6. 转义:在正则表达式中转义需要注意哪些问题?

转义字符在正则表达式中非常重要,许多元字符(如.*[]等)在没有转义的情况下有特殊含义。如果我们想要匹配这些字符本身,就需要使用反斜杠进行转义。

常见转义字符

  • \\ 用于匹配反斜杠本身。
  • \\. 用于匹配句点(.)字符,而非任意字符。
  • \\[\\] 用于匹配方括号 []

示例:

java 复制代码
// 匹配点号
String regex = "\\.";
String input = "example.com";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
System.out.println(matcher.find());  // 输出: true

注意事项

  • 在字符串中,反斜杠是转义字符,所以下划线 \ 需要写成 \\
  • 在某些情况下,正则中的转义字符需要额外小心,尤其是在不同的编程语言和库中,反斜杠的处理可能略有不同。

7. 正则有哪些常见的流派及其特性?

正则表达式的实现方式有不同的流派,主要包括以下几种:

  • NFA(非确定性有限自动机):大多数现代正则引擎采用NFA模式,即正则引擎通过回溯来寻找匹配,比较灵活,但性能可能受到影响,尤其在遇到复杂或贪婪的模式时。
  • DFA(确定性有限自动机):DFA正则引擎一次性扫描所有可能的匹配,效率较高,但表达能力较弱,通常不支持回溯。
  • POSIX:POSIX规范是UNIX系统中的标准正则表达式实现,具有严格的语法要求,支持常规的正则操作,但不支持更复杂的功能。

不同的流派在正则表达式的匹配效率、灵活性以及表达能力上有所不同,开发人员在选择时需要根据实际的需求进行权衡。

8. 应用 1:正则如何处理 Unicode 编码的文本?

Unicode 是一种字符编码标准,支持全球大部分文字和符号。正则表达式也可以处理Unicode编码的文本,但需要注意匹配模式和字符类别。

常见问题

  • 在正则表达式中,默认匹配的是单字节字符。若需要处理Unicode字符集中的多字节字符(如中文),需要指定Unicode匹配模式。
  • \p{} 可以用来匹配特定Unicode字符类别,如字母、数字等。

示例:

java 复制代码
// 匹配所有汉字字符
String regex = "\\p{IsHan}+";
String input = "Hello 你好 World";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
    System.out.println(matcher.group());  // 输出: 你好
}

解释

  • \\p{IsHan}:匹配汉字字符类别。

9. 应用 2:如何在编辑器中使用正则完成工作?

许多现代文本编辑器(如 VSCode、Sublime Text)都支持正则表达式来查找和替换文本。这对于处理大量文本、日志分析、代码重构等任务非常有用。

示例

  • 查找所有变量定义

    假设你想查找所有的 Java 变量定义,可以使用类似 \b\w+\s+\w+\b 的正则来匹配。

  • 替换函数调用中的参数

    假设你想替换函数调用的参数格式,可以使用正则替换。比如,将 foo(a, b) 替换成 foo(a; b)

10. 应用 3:如何用正则让文本处理能力上一个台阶?

正则表达式可以极大地增强文本处理能力,尤其是对复杂文本的处理。你可以利用正则来解析复杂的日志、抓取网页内容、进行数据验证等。

应用场景

  • 日志分析:通过正则提取日志中的关键字段,例如日期、错误代码、日志级别等。
  • Web Scraping:使用正则从网页中提取数据,例如标题、文章内容等。

示例:

java 复制代码
// 从日志中提取错误信息
String regex = "ERROR\\s+(\\d+)\\s+(.+)";
String input = "ERROR 404 Page Not Found\nERROR 500 Internal Server Error";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
    System.out.println("错误代码: " + matcher.group(1));  // 输出错误代码
    System.out.println("错误信息: " + matcher.group(2));  // 输出错误描述
}

11. 如何理解正则表达式的匹配原理以及优化原则?

理解正则表达式的匹配原理是掌握其高效应用的关键。正则表达式的匹配过程通常是通过 有限状态机(FSM) 来实现的。正则引擎从左到右扫描输入字符串,并尝试与正则模式匹配。在匹配过程中,正则引擎会执行以下步骤:

  1. 字符匹配:每次尝试匹配输入字符串的一个字符。
  2. 回溯:当匹配失败时,正则引擎会回溯到上一个匹配位置,重新尝试匹配其他可能的模式。
  3. 正向搜索:正则引擎通常会从字符串的左侧开始扫描,遇到第一个符合条件的匹配时就停止。

优化原则

  • 避免使用贪婪量词 :贪婪量词会尝试匹配尽可能多的字符,这可能导致性能下降,特别是在长字符串中。可以使用非贪婪量词(*?, +?)来减少匹配范围。
  • 使用 anchors(锚点) :通过 ^$ 来限制匹配的起始和结束位置,避免正则引擎遍历整个字符串。
  • 精简表达式:避免使用过多的分组和不必要的重复模式,以减小匹配时间。

示例:

java 复制代码
// 贪婪匹配 vs 非贪婪匹配
String regex1 = "a.*b";  // 贪婪模式,尽量匹配更多字符
String regex2 = "a.*?b";  // 非贪婪模式,尽量匹配较少字符

String input = "a1b2c3b";
Pattern pattern1 = Pattern.compile(regex1);
Pattern pattern2 = Pattern.compile(regex2);

Matcher matcher1 = pattern1.matcher(input);
Matcher matcher2 = pattern2.matcher(input);

System.out.println(matcher1.find());  // 输出: true, 匹配到 a1b2c3b
System.out.println(matcher2.find());  // 输出: true, 匹配到 a1b

优化建议

  • 在需要匹配到特定字符的情况下,尽量使用精确的匹配方式而不是广泛的通配符。
  • 对于有大量文本需要匹配的情况,避免使用像 .* 这样的模式,改用更具体的匹配条件,如 \d+ 来限制匹配数字。

12. 问题集锦:详解正则表达式常见问题及解决方案

在使用正则表达式时,常常会遇到一些特定问题。这里列举了几个常见的正则问题,并提供解决方案。

  1. 问题:如何处理多行文本的匹配?

    • 默认情况下,正则表达式只会匹配单行文本。如果需要匹配多行文本,可以使用 Pattern.MULTILINE 标志。

    示例:

    java 复制代码
    String regex = "^hello";  // 匹配以 hello 开头的行
    String input = "hello world\nhello java\ngoodbye world";
    Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
    Matcher matcher = pattern.matcher(input);
    
    while (matcher.find()) {
        System.out.println("匹配到: " + matcher.group());
    }

    输出:

    复制代码
    匹配到: hello
    匹配到: hello
  2. 问题:如何处理复杂的文本替换?

    • 对于复杂的文本替换,可以使用正则表达式中的分组和引用来精确替换指定部分。

    示例:

    java 复制代码
    // 替换日期格式:yyyy-mm-dd -> dd/mm/yyyy
    String regex = "(\\d{4})-(\\d{2})-(\\d{2})";
    String replacement = "$3/$2/$1";  // $1, $2, $3 表示捕获组
    String input = "2021-12-31";
    String output = input.replaceAll(regex, replacement);
    System.out.println(output);  // 输出: 31/12/2021
  3. 问题:正则表达式匹配时如何避免死循环?

    • 贪婪模式可能会导致正则引擎在一些情况下陷入死循环,特别是当模式中存在大量回溯时。优化贪婪模式,避免不必要的回溯。

    解决方案

    • 使用非贪婪量词 *?+?,使得匹配尽可能小。
    • 使用预设的匹配条件,如限定范围 [a-z]{3,10} 来防止过多回溯。

13. 正则表达式的性能优化

正则表达式的性能是我们在实际应用中必须关注的一个重要方面,尤其是在大数据量或复杂模式匹配的情况下。如果正则表达式编写不当,可能导致性能瓶颈。

常见的性能问题

  1. 回溯问题:正则表达式的回溯机制会尝试所有可能的匹配路径,导致执行时间显著增加。在处理不符合预期的输入时,回溯可能会导致性能严重下降。

    优化策略

    • 尽量避免使用复杂的捕获组和多个|操作符,使用更简单的表达式。
    • 使用^$等锚点来限制匹配的起始和结束位置,避免多次回溯。
  2. 贪婪匹配问题 :贪婪量词(如*+)会尽可能多地匹配字符,这在一些情况下可能导致不必要的长时间匹配。

    优化策略

    • 使用非贪婪量词(如*?+?)来尽量减少匹配的字符数量。
    • 优化模式结构,避免过度匹配。
  3. 避免重复计算:某些正则表达式在匹配时可能需要重复计算相同的部分,导致不必要的性能消耗。

    优化策略

    • 使用懒惰匹配来减少不必要的计算。
    • 对于复杂的正则,考虑将表达式拆解成多个简单的部分,逐步进行匹配。

示例:

java 复制代码
// 贪婪匹配的性能问题
String regex = "a.*b";  // 如果输入字符串中有多个'a'和'b',则可能导致多次回溯
String input = "aaaaaabbbbbbbbbb";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
System.out.println(matcher.find());  // 输出: true

// 非贪婪匹配
String regexNonGreedy = "a.*?b";  // 使用非贪婪量词
matcher = Pattern.compile(regexNonGreedy).matcher(input);
System.out.println(matcher.find());  // 输出: true

在这个示例中,贪婪匹配会尝试匹配尽可能长的字符串,而非贪婪匹配会尽量少匹配字符,从而减少回溯。

14. 正则表达式的安全性

在某些情况下,恶意用户可能会构造特定的正则表达式,从而导致正则引擎出现拒绝服务(DoS)攻击 。这种攻击通常被称为ReDoS(Regular Expression Denial of Service),其核心思想是通过让正则表达式执行大量的回溯操作,从而耗尽计算资源,导致服务崩溃。

ReDoS攻击的常见模式

  • 灾难性回溯 :当正则表达式中包含大量的"贪婪"量词或者选择结构(|)时,输入数据的长度或结构会导致大量的回溯操作,从而消耗大量时间和计算资源。

防御策略

  • 避免复杂的贪婪量词 :避免使用.*.+等可能导致回溯过多的模式,尤其是当用户输入数据不受控制时。
  • 使用合适的正则引擎 :某些现代正则引擎对这种类型的攻击具有内建的防御机制,例如使用回溯控制算法来限制回溯的次数。

示例:

java 复制代码
// 容易被ReDoS攻击的正则
String regex = "(a+)+b";  // 这里存在潜在的回溯问题
String input = "a".repeat(10000) + "b";  // 大量'a'字符
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
System.out.println(matcher.matches());  // 可能会出现性能问题

防范ReDoS攻击的优化方式是尽量避免使用容易引发回溯问题的正则表达式,尤其是在用户输入未加验证的情况下。

15. 正则表达式的调试与工具使用

在开发中,调试正则表达式是一项非常重要的技能,尤其是当我们面对复杂的模式匹配时。幸运的是,许多工具和IDE插件都提供了调试支持。

调试技巧

  1. 逐步测试:将正则表达式拆分成小部分,逐步测试每一部分的匹配情况。
  2. 可视化工具 :使用在线正则表达式调试器(如regex101)来可视化和测试正则表达式。它们会显示每个部分的匹配过程,并指出可能存在的错误。

示例

在正则调试器中输入正则"(\\d+)-(\\d+)"和输入字符串"123-456", 工具会显示它如何逐步匹配数字并分组。通过这种可视化调试,我们能够清楚地看到正则表达式是如何工作的,从而避免常见的匹配错误。

16. 常见问题及解决方案

正则表达式在使用过程中经常会遇到一些常见问题,以下是几个常见的案例及解决方案。

  • 问题 1:正则表达式中包含特殊字符怎么办?

    • 解决方案:在正则表达式中需要匹配某些特殊字符(如.*+等)时,要使用反斜杠(\)进行转义。

    • 示例:

      java 复制代码
      // 匹配字符串中的'.'
      String regex = "\\.";  // 使用转义字符
      String input = "Hello. World";
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(input);
      System.out.println(matcher.find());  // 输出: true
  • 问题 2:如何匹配多种不同格式的日期?

    • 解决方案:使用正则表达式匹配不同的日期格式。例如,可以设计一个表达式来匹配yyyy-mm-ddmm/dd/yyyy两种格式。

    • 示例:

      java 复制代码
      // 匹配yyyy-mm-dd格式和mm/dd/yyyy格式的日期
      String regex = "(\\d{4})-(\\d{2})-(\\d{2})|(\\d{2})/(\\d{2})/(\\d{4})";
      String input = "2022-10-15 or 10/15/2022";
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(input);
      while (matcher.find()) {
          System.out.println(matcher.group());  // 输出: 2022-10-15, 10/15/2022
      }

17. 正则表达式的调试与可视化

在开发过程中,正则表达式的调试往往是一个挑战,尤其是在正则表达式非常复杂的情况下。幸运的是,现在有许多工具可以帮助我们进行调试和可视化,使得正则的理解更加直观。

常用调试工具

  1. regex101
    regex101 是一个非常受欢迎的在线正则表达式调试工具,支持多种语言(包括 Java、Python、JavaScript 等)。该工具提供了实时的正则匹配结果展示,并且会详细说明正则表达式的每一部分如何进行匹配。

  2. Regexr
    Regexr 是另一个强大的正则调试工具,它提供了实时匹配、正则构建帮助和常见正则表达式的示例。它对于初学者来说非常友好。

如何使用这些工具

  • 在工具中输入正则表达式和待匹配文本。
  • 查看每一部分的匹配过程和正则语法的解释。
  • 可以逐步调整正则表达式,并实时观察匹配结果,以便优化正则表达式。

例如,在 regex101 中,我们可以输入正则 (\d+)\s+(\w+) 和文本 "123 hello",它会实时显示匹配的部分,并分解每个分组。

18. 正则表达式与Unicode文本处理

正则表达式的强大之处之一就是它能够处理各种字符编码,包括 Unicode 编码。在多语言应用程序中,Unicode 已经成为了标准字符集,处理Unicode字符变得尤为重要。

处理 Unicode 编码的正则表达式

  • 正则表达式可以通过 \uXXXX 来匹配 Unicode 字符。例如,\u0041 匹配的是大写字母"A"。
  • 在匹配中文字符时,我们可以使用 \p{InCJKUnifiedIdeographs} 来匹配所有汉字字符。

示例:

java 复制代码
// 匹配所有中文字符
String regex = "\\p{IsHan}+";
String input = "我爱编程";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
    System.out.println(matcher.group());  // 输出: 我爱编程
}

// 匹配所有数字(包括Unicode中的数字)
String regexUnicode = "\\p{Nd}+";  // \p{Nd} 用于匹配所有数字
String inputUnicode = "12345 ١٢٣٤٥";  // 包含阿拉伯数字
Pattern patternUnicode = Pattern.compile(regexUnicode);
Matcher matcherUnicode = patternUnicode.matcher(inputUnicode);
while (matcherUnicode.find()) {
    System.out.println(matcherUnicode.group());  // 输出: 12345, ١٢٣٤٥
}

注意事项

  1. 正则表达式中的Unicode处理能力非常强大,但是需要确保正则引擎支持Unicode,否则会出现匹配失败。
  2. 使用Unicode正则时,特别是针对多语言或特定地区的字符集时,需要特别注意正则表达式的兼容性和执行效率。

19. 正则表达式与多行匹配

在处理多行文本时,我们经常需要在行首和行尾进行匹配,这时使用正则表达式时需要特别小心。

多行匹配

  • 默认情况下,正则表达式使用的是单行模式,在这种模式下,^ 只能匹配文本的开始,$ 只能匹配文本的结束。
  • 使用 (?m) 模式(多行模式),可以让 ^$ 匹配每一行的开始和结束,而不仅仅是整个文本的开始和结束。

示例:

java 复制代码
String regex = "(?m)^\\d+";
String input = "123\n456\n789";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
    System.out.println(matcher.group());  // 输出: 123, 456, 789
}

在上面的代码中,(?m) 启用了多行模式,^ 匹配每行的开头,而不是整个文本的开头。

20. 常见的正则表达式流派及其特性

正则表达式的引擎存在不同的流派,它们在正则表达式的实现上有一定的差异。不同的正则引擎可能会有不同的性能特征、语法支持以及功能扩展。

常见的正则引擎流派

  1. NFA(非确定性有限自动机):这种类型的正则引擎采用了回溯机制,常见的如 Python 的 re、JavaScript 的正则引擎等。
  2. DFA(确定性有限自动机):DFA 模式的正则引擎在执行时不依赖回溯,因此通常更高效。它适用于不涉及复杂回溯的匹配任务,如一些基于正则的搜索引擎。
  3. Thompson 构造算法 :这种方法的正则引擎会将正则表达式转换为状态机并执行优化,Java 的 Pattern 类使用的正则引擎就采用了类似的策略。

优缺点

  • NFA:回溯机制使得它在复杂模式匹配时非常灵活,但在极端情况下性能较差,可能导致回溯过多。
  • DFA:没有回溯机制,执行速度较快,但对于某些模式可能需要更多的内存。
  • Thompson 算法:提供了一种比较高效的状态机生成方式,平衡了灵活性和性能。

21. 常见问题集锦:详解正则表达式常见问题及解决方案

  1. 问题 1:如何匹配不包含某个字符的字符串?

    • 解决方案:可以使用负向前瞻(negative lookahead)来匹配不包含特定字符的字符串。

    • 示例:

      java 复制代码
      // 匹配不包含字母 'a' 的字符串
      String regex = "^(?!.*a).*";  // 负向前瞻
      String input = "Hello, World!";
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(input);
      System.out.println(matcher.matches());  // 输出: true
  2. 问题 2:正则表达式中如何匹配换行符?

    • 解决方案:换行符通常用 \n\r\n 来表示。

    • 示例:

      java 复制代码
      // 匹配换行符
      String regex = "\\n";
      String input = "Hello\nWorld";
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(input);
      while (matcher.find()) {
          System.out.println("Found newline!");  // 输出: Found newline!
      }
  3. 问题 3:如何避免正则表达式中的重叠匹配?

    • 解决方案:使用非捕获组((?:...))来避免不必要的匹配,同时使用非贪婪量词来避免重叠匹配。

    • 示例:

      java 复制代码
      // 避免重叠匹配
      String regex = "(?:\\d+)";
      String input = "123 456";
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(input);
      while (matcher.find()) {
          System.out.println(matcher.group());
      }

相关推荐
吴声子夜歌18 小时前
正则指引——Ruby
开发语言·正则表达式·ruby
吴声子夜歌20 小时前
正则指引——Golang
开发语言·golang·正则表达式
吴声子夜歌2 天前
正则指引——PHP
开发语言·正则表达式·php
吴声子夜歌4 天前
正则指引——断言
正则表达式
吴声子夜歌4 天前
正则指引——匹配原理
java·正则表达式
吴声子夜歌5 天前
正则表达式——环视
开发语言·正则表达式
吴声子夜歌6 天前
正则表达式——边界
正则表达式
营养充电站6 天前
C++23 新特性在 CLion 中的实战体验
macos·docker·jupyter·正则表达式
吴声子夜歌6 天前
正则表达式——字符组
正则表达式