正则表达式超详细版

一、基本概念

正则表达式(Regular Expression)是一种强大的文本处理工具,用于匹配、查找、替换字符串中的特定模式。它通过一系列预定义的语法规则,描述字符串的结构特征,广泛应用于数据验证、文本解析、日志分析、搜索引擎等领域。

二、基础语法(核心元字符与规则)

正则表达式的语法由「普通字符」和「元字符」组成,元字符是具有特殊含义的符号,掌握它们是使用正则的基础。

1. 普通字符

  • 直接匹配自身,无特殊含义(如 ab1、 空格等)。
  • 示例:abc 匹配字符串 "abc"123 匹配 "123"

2. 核心元字符(按功能分类)

元字符 功能说明 示例
. 匹配任意单个字符(默认不匹配换行符 \n,部分语言可通过修饰符改变)。 a.b 匹配 "axb""a1b""a#b"(不匹配 "a\nb")。
^ 匹配字符串开头(多行模式下匹配每行开头)。 ^hello 匹配 "hello world"(开头是 hello),不匹配 "xhello"
$ 匹配字符串结尾(多行模式下匹配每行结尾)。 world$ 匹配 "hello world"(结尾是 world),不匹配 "worldx"
* 匹配前面的元素 0 次或多次(贪婪匹配:尽可能多匹配)。 ab* 匹配 "a""ab""abb""abbb"
+ 匹配前面的元素 1 次或多次(贪婪匹配)。 ab+ 匹配 "ab""abb"(不匹配 "a")。
? 匹配前面的元素 0 次或 1 次(可选匹配)。 ab? 匹配 "a""ab"(不匹配 "abb")。
{n} 匹配前面的元素 恰好 n 次(n 为非负整数)。 a{3} 匹配 "aaa"(不匹配 "aa""aaaa")。
{n,} 匹配前面的元素 至少 n 次(贪婪匹配)。 a{2,} 匹配 "aa""aaa""aaaa"
{n,m} 匹配前面的元素 n 到 m 次(n ≤ m,贪婪匹配)。 a{2,3} 匹配 "aa""aaa"(不匹配 "a""aaaa")。
` ` 逻辑「或」,匹配左边或右边的模式(优先级最低,需用括号提升优先级)。
() 分组:将多个字符视为一个整体,同时捕获匹配结果(可通过反向引用使用)。 (ab)+ 匹配 "ab""abab"(\w+)\s+(\w+) 捕获两个单词(如 "hello world")。
\ 转义字符:取消元字符的特殊含义,或表示预定义字符类(如 \d\s)。 a\.b 匹配 "a.b". 作为普通字符);\* 匹配 "*"
[] 字符类:匹配括号内任意一个字符(支持范围表示,^ 表示否定)。 [abc] 匹配 "a""b""c"[^abc] 匹配非 a/b/c 的字符。
[-] 字符类内的范围符:表示连续字符集(如字母、数字范围)。 [a-z] 匹配小写字母;[0-9] 匹配数字;[a-zA-Z0-9] 匹配字母数字。

3. 预定义字符类(简化写法)

为了简化常见的字符匹配,正则提供了预定义的字符类(部分需结合修饰符使用):

预定义类 等价于 功能说明
\d [0-9] 匹配任意数字(digit)。
\D [^0-9] 匹配任意非数字。
\w [a-zA-Z0-9_] 匹配字母、数字、下划线(word 字符,注意不包含空格和特殊字符)。
\W [^a-zA-Z0-9_] 匹配非字母、数字、下划线。
\s [ \t\n\r\f\v] 匹配任意空白字符(space:空格、制表符 \t、换行符 \n 等)。
\S [^ \t\n\r\f\v] 匹配任意非空白字符。
\b - 匹配单词边界(单词与非单词的分隔处,如 "hello world" 中的空格两侧)。
\B - 匹配非单词边界(如 "helloworld" 中两个单词的连接处)。
\n - 匹配换行符(部分语言支持 \r\n 匹配 Windows 换行)。
\t - 匹配制表符。

示例:

  • \d{3}-\d{4} 匹配 "123-4567"(3 位数字 + 横杠 + 4 位数字)。
  • \w+@\w+\.\w+ 匹配简单邮箱(如 "test123@example.com")。
  • \bhello\b 匹配独立的单词 "hello"(不匹配 "helloworld""xhello")。

三、核心特性(进阶用法)

掌握基础语法后,需理解正则的核心特性(贪婪 / 非贪婪、分组 / 捕获、断言等),才能应对复杂场景。

1. 贪婪匹配与非贪婪匹配

默认情况下,正则的量词(*+?{n,m})是「贪婪的」------ 尽可能匹配更多字符。在量词后加 ? 可变为「非贪婪」------ 尽可能匹配更少字符。

模式 类型 示例(匹配字符串 "aabbaabcc"
a.*b 贪婪 匹配 "aabbaab"(从第一个 a 到最后一个 b)。
a.*?b 非贪婪 匹配 "aab"(从第一个 a 到最近的 b)。
a.+c 贪婪 匹配 "aabbaabcc"(从第一个 a 到最后一个 c)。
a.+?c 非贪婪 匹配 "aabbaabc"(从第一个 a 到最近的 c)。

2. 分组与捕获

() 不仅能将模式分组(视为整体),还能「捕获」匹配到的内容,后续可通过「反向引用」或编程接口获取。

(1)普通捕获组
  • 语法:(pattern)
  • 捕获的内容按分组顺序编号(从 1 开始),可通过 \1\2...(正则内)或编程变量(如 Python 的 group(1))引用。

示例:

  • 匹配重复单词:(\w+)\s+\1解释:(\w+) 捕获第一个单词,\s+ 匹配空格,\1 引用第一个捕获的单词,可匹配 "hello hello""test test"
  • 提取日期中的年、月、日:(\d{4})-(\d{2})-(\d{2})匹配 "2025-11-21" 后,捕获组 1 = "2025",组 2 = "11",组 3 = "21"
(2)非捕获组

若只需分组(不捕获结果),用 (?:pattern),可提升性能(避免不必要的内存占用)。

示例:

  • (?:ab)+ 匹配 "ab""abab"(不捕获 "ab",仅作为整体匹配)。
(3)命名捕获组

为捕获组命名,便于后续引用(避免按编号混淆),语法:(?<name>pattern)(部分语言支持,如 Python、JavaScript、Java)。

示例:

  • 提取日期:(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})匹配后可通过名称引用(如 Python 的 group("year")),更直观。

3. 零宽断言(Lookaround)

零宽断言是「匹配位置」的模式,不消耗字符(仅判断当前位置前后是否满足条件),分为「先行断言」和「后行断言」。

(1)先行断言(Lookahead)

判断当前位置后面是否满足条件,语法:

  • 正向先行:(?=pattern) → 后面必须是 pattern。
  • 负向先行:(?!pattern) → 后面必须不是 pattern。

示例:

  • 匹配「后面是数字的字母」:[a-zA-Z](?=\d)匹配 "a1" 中的 "a""b23" 中的 "b"(后面必须跟数字)。
  • 匹配「后面不是数字的字母」:[a-zA-Z](?!\d)匹配 "ab" 中的 "a""c#" 中的 "c"(后面不是数字)。
  • 验证密码(必须包含数字):^(?=.*\d).{6,12}$解释:^ 开头,(?=.*\d) 后面必须有至少一个数字,.{6,12} 匹配 6-12 个任意字符,$ 结尾。
(2)后行断言(Lookbehind)

判断当前位置前面是否满足条件,语法:

  • 正向后行:(?<=pattern) → 前面必须是 pattern。
  • 负向后行:(?<!pattern) → 前面必须不是 pattern。

示例:

  • 匹配「前面是数字的字母」:(?<=\d)[a-zA-Z]匹配 "1a" 中的 "a""23b" 中的 "b"(前面是数字)。
  • 匹配「前面不是数字的字母」:(?<!\d)[a-zA-Z]匹配 "xa" 中的 "a""#b" 中的 "b"(前面不是数字)。
  • 提取「 后面的数字」:`(?<=\$)\d+`匹配`"123"中的"123""price: 45"`中的`"45"\`(前面是 )。

4. 模式修饰符(Flags)

修饰符用于改变正则的匹配行为(如忽略大小写、多行匹配等),不同语言的表示方式不同(如 Python 用 re.IGNORECASE,JavaScript 用 /pattern/gi)。

常见修饰符:

修饰符 作用说明
i 忽略大小写(case-insensitive):a 可匹配 AB 可匹配 b
g 全局匹配(global):找到所有匹配项,而非第一个(部分语言默认全局)。
m 多行模式(multi-line):^ 匹配每行开头,$ 匹配每行结尾(默认仅匹配整体开头 / 结尾)。
s 单行模式(single-line):. 匹配所有字符(包括换行符 \n,默认不匹配)。
u Unicode 模式:支持 Unicode 字符(如 \p{L} 匹配任意语言的字母)。
x 忽略空格和注释(extended):便于编写复杂正则(用 # 写注释)。

示例:

  • 忽略大小写匹配:/hello/i 匹配 "Hello""HELLO""hello"
  • 多行模式匹配:/^hello/m 匹配 "hello\nworld\nhello" 中的两个 "hello"(每行开头)。
  • 单行模式匹配:/a.b/s 匹配 "a\nb". 匹配换行符)。

四、常见应用场景(实战示例)

正则的核心价值是解决文本处理问题,以下是高频场景的实战示例:

1. 数据验证

示例 1:验证邮箱地址
cs 复制代码
using System;
using System.Text.RegularExpressions;

public class EmailValidator
{
    public static bool IsValidEmail(string email)
    {
        // 正则表达式:^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
        string pattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
        return Regex.IsMatch(email, pattern);
    }

    public static void Main()
    {
        string[] emails = {
            "test@example.com",
            "user.name+tag@example.co.uk",
            "invalid-email",
            "another.invalid@.com"
        };

        foreach (var email in emails)
        {
            Console.WriteLine($"{email}: {IsValidEmail(email)}");
        }
    }
}

输出:

cs 复制代码
test@example.com: True
user.name+tag@example.co.uk: True
invalid-email: False
another.invalid@.com: False

示例 2:验证手机号(中国大陆)
cs 复制代码
public class PhoneValidator
{
    public static bool IsValidPhone(string phone)
    {
        // 正则表达式:^1[3-9]\d{9}$
        string pattern = @"^1[3-9]\d{9}$";
        return Regex.IsMatch(phone, pattern);
    }

    public static void Main()
    {
        string[] phones = {
            "13812345678",
            "19987654321",
            "1234567890",
            "138123456789"
        };

        foreach (var phone in phones)
        {
            Console.WriteLine($"{phone}: {IsValidPhone(phone)}");
        }
    }
}

2. 文本提取

示例 3:从 HTML 中提取链接
cs 复制代码
using System;
using System.Text.RegularExpressions;

class LinkExtractor
{
    static void Main()
    {
        string html = @"
            <a href=""https://www.example.com"">Example</a>
            <a href=""https://www.google.com"">Google</a>
            <img src=""image.jpg"">
        ";

        // 正则表达式:<a\s+href=""([^""]*)""
        string pattern = @"<a\s+href=""([^""]*)""";
        MatchCollection matches = Regex.Matches(html, pattern);

        foreach (Match match in matches)
        {
            Console.WriteLine(match.Groups[1].Value);
        }
    }
}

输出:

cs 复制代码
https://www.example.com
https://www.google.com

示例 4:提取字符串中的所有数字
cs 复制代码
class NumberExtractor
{
    static void Main()
    {
        string input = "订单号:20230518001,金额:99.9元,数量:10";
        string pattern = @"\d+\.?\d*"; // 匹配整数或小数

        MatchCollection matches = Regex.Matches(input, pattern);
        foreach (Match match in matches)
        {
            Console.WriteLine(match.Value);
        }
    }
}

输出:

cs 复制代码
20230518001
99.9
10

3. 文本替换与格式化

示例 5:替换字符串中的敏感信息
cs 复制代码
class TextReplacer
{
    static void Main()
    {
        string input = "手机号:15112347676,身份证号:410123194910011234";
        
        // 替换手机号中间4位为****
        string phonePattern = @"(1[3-9])\d{4}(\d{4})";
        string result = Regex.Replace(input, phonePattern, "$1****$2");

        // 替换身份证号中间8位为********
        string idPattern = @"(^\d{6}|\d{8})(\d{4}$)";
        result = Regex.Replace(result, idPattern, "$1********$2");

        Console.WriteLine(result);
    }
}

输出:

cs 复制代码
手机号:151****7676,身份证号:410123********1234

示例 6:格式化日期(MM/DD/YYYY → YYYY-MM-DD)
cs 复制代码
class DateFormatter
{
    static void Main()
    {
        string input = "Today is 11/21/2025";
        string pattern = @"\b(\d{2})/(\d{2})/(\d{4})\b";
        
        // 替换为 YYYY-MM-DD
        string result = Regex.Replace(input, pattern, "$3-$1-$2");
        Console.WriteLine(result);
    }
}

输出:

cs 复制代码
Today is 2025-11-21

4. 高级应用:正则表达式分组与命名捕获

示例 7:解析日志文件

假设日志格式为:[2025-11-21 14:30:00] [INFO] User 'admin' logged in.

cs 复制代码
class LogParser
{
    static void Main()
    {
        string log = "[2025-11-21 14:30:00] [INFO] User 'admin' logged in.";
        
        string pattern = @"\[(.*?)\] \[(.*?)\] (.*)";
        Match match = Regex.Match(log, pattern);

        if (match.Success)
        {
            string timestamp = match.Groups[1].Value;
            string level = match.Groups[2].Value;
            string message = match.Groups[3].Value;
            
            Console.WriteLine($"时间:{timestamp}\n级别:{level}\n内容:{message}");
        }
    }
}

输出:

cs 复制代码
时间:2025-11-21 14:30:00
级别:INFO
内容:User 'admin' logged in.

示例 8:使用命名捕获组
cs 复制代码
class NamedGroupExample
{
    static void Main()
    {
        string input = "Name: John, Age: 30, Email: john@example.com";
        
        string pattern = @"Name: (?<name>\w+), Age: (?<age>\d+), Email: (?<email>[^,]+)";
        Match match = Regex.Match(input, pattern);

        if (match.Success)
        {
            Console.WriteLine($"姓名:{match.Groups["name"].Value}");
            Console.WriteLine($"年龄:{match.Groups["age"].Value}");
            Console.WriteLine($"邮箱:{match.Groups["email"].Value}");
        }
    }
}

五、注意事项与性能优化

1. 注意事项

  • 转义问题 :不同语言中,正则的转义规则不同(如 Python 字符串中 \ 需转义为 \\,JavaScript 中直接写 \)。
  • 部分匹配 vs 完全匹配 :验证格式时必须加 ^$(如手机号 1[3-9]\d{9} 会匹配 "a13812345678b",加 ^$ 才会完全匹配)。
  • 换行符处理 :默认 . 不匹配 \n,需用 (?s) 修饰符或 [\s\S](匹配所有字符)。
  • Unicode 支持 :处理多语言文本时,需开启 Unicode 模式(如 \p{L} 匹配任意语言字母,而非仅 [a-zA-Z])。

2. 性能优化

复杂正则可能导致回溯过多,影响性能,需注意:

  • 避免嵌套量词(如 (a*)*),容易引发回溯爆炸。
  • 用具体字符类代替 .(如匹配数字用 \d 而非 .,减少不必要的匹配)。
  • 优先使用非贪婪匹配(.*?)避免过度匹配,但不要滥用(非贪婪也可能增加回溯)。
  • 用原子组 (?>pattern) 避免回溯(原子组匹配后不可回溯,适合确定的模式)。
  • 拆分复杂正则(如长正则拆分为多个简单正则,分步处理)。

六、常见正则表达式示例(直接复用)

1. 验证类

| 场景 | 正则表达式(C# 字符串需转义,或用 @ 逐字字符串) |
| 手机号(中国大陆) | ^1[3-9]\d{9} | | 邮箱 | \^\[a-zA-Z0-9._%+-\]+@\[a-zA-Z0-9.-\]+\\.\[a-zA-Z\]{2,} |
| 身份证号(18 位) | ^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}([0-9]|X|x) | | URL(http/https) | \^https?://\[\^\\s\]+ |
| 日期(yyyy-MM-dd) | ^[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ |

密码(8-20 位,含大小写字母、数字、特殊字符) ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,20}$

2. 提取类

| 场景 | 正则表达式 |
| 提取所有数字 | \d+ |
| 提取所有链接 | https?://[^\s]+ |
| 提取 HTML 标签内容(如 <title>xxx</title>) | <title>(.*?)</title> |

提取邮箱地址 [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}

3. 替换类

| 场景 | 正则表达式 |
| 去除所有空格 | \s+ |
| 格式化手机号(13812345678 → 138-1234-5678) | (\d{3})(\d{4})(\d{4}) |
| 替换 HTML 标签(去除所有标签) | <[^>]+> |

敏感词替换("垃圾""废物" 替换为 "***") (垃圾|废物)

希望对大家有所帮助。感谢大家的关注和点赞。

相关推荐
m0_488777652 小时前
正则表达式与文本处理器以及命令小工具
正则表达式·命令小工具
青衫码上行2 天前
【Java Web学习 | 第14篇】JavaScript(8) -正则表达式
java·前端·javascript·学习·正则表达式
beijingliushao3 天前
95-Python爬虫-正则表达式
爬虫·python·正则表达式
前端 贾公子3 天前
正则表达式(/g修饰符)踩坑
正则表达式
q***84573 天前
Java进阶,时间与日期,包装类,正则表达式
java·mysql·正则表达式
非得登录才能看吗?10 天前
正则表达式入门
正则表达式
小飞大王66610 天前
JavaScript基础知识总结(四):常见内置构造函数,正则表达式,作用域与闭包
前端·javascript·正则表达式
BenChuat11 天前
正则表达式详解与实战指南:从入门到常见案例
正则表达式
蒋星熠12 天前
爬虫中Cookies模拟浏览器登录技术详解
开发语言·爬虫·python·正则表达式·自动化·php·web