一、使用原理
- 模式匹配机制:
- 在 C# 中,正则表达式通过定义一种模式来描述文本的特征。例如,
\d表示匹配任意一个数字字符。当使用正则表达式进行匹配时,正则表达式引擎会从输入文本的起始位置开始,逐个字符地将输入文本与模式进行比较。 - 引擎尝试找到一个连续的字符序列,该序列与整个模式完全匹配。如果找到了这样的序列,则匹配成功;否则,匹配失败。
- 在 C# 中,正则表达式通过定义一种模式来描述文本的特征。例如,
- 回溯机制:
- 当正则表达式中存在可选部分(如
a?表示a可选出现一次或不出现)或重复部分(如a+表示a出现一次或多次)时,可能会出现多种匹配的可能性。在这种情况下,正则表达式引擎会使用回溯机制。 - 例如,对于模式
a(b|c)+和输入文本abcc,引擎首先匹配a,然后遇到(b|c)+,它会尝试匹配b,接着匹配第一个c,然后再次匹配c。如果后续还有更多文本,并且匹配失败,引擎会回溯到上一个选择点,尝试其他可能的匹配路径,直到找到成功匹配或确定无法匹配为止。
- 当正则表达式中存在可选部分(如
- 捕获组:
- 捕获组是正则表达式中的一个重要概念,它允许你将匹配的一部分文本提取出来。通过将模式的一部分用圆括号
()括起来,可以定义一个捕获组。 - 例如,对于模式
(\d{3})-(\d{3})-(\d{4})(用于匹配美国电话号码格式,如123 - 456 - 7890),有三个捕获组。在匹配成功后,可以通过Match.Groups属性访问这些捕获组,每个捕获组包含了相应部分的匹配文本。
- 捕获组是正则表达式中的一个重要概念,它允许你将匹配的一部分文本提取出来。通过将模式的一部分用圆括号
- 编译与执行:
- 在 C# 中,当使用
Regex类进行正则表达式操作时,Regex类会将正则表达式模式编译成一种内部表示形式,以便更高效地执行匹配操作。 - 如果需要多次使用同一个正则表达式模式,可以使用
Regex.CompileToAssembly方法将正则表达式编译成程序集,进一步提高性能。这在一些需要频繁进行正则匹配的场景(如文本处理的循环中)非常有用。
- 在 C# 中,当使用
二、应用场景
- 数据验证:
- 邮箱地址验证:确保用户输入的邮箱地址符合正确的格式,例如
user@domain.com。常见的正则表达式模式为^[a-zA-Z0 - 9_.+-]+@[a-zA-Z0 - 9 -]+\.[a-zA-Z0 - 9-.]+$。 - 电话号码验证:验证电话号码是否符合特定地区的格式。例如,美国电话号码可以用
^\d{3}-\d{3}-\d{4}$来验证,其中^\d{3}表示以三个数字开头,-\d{3}表示中间是一个短横线和三个数字,-\d{4}$表示最后是一个短横线和四个数字。
- 邮箱地址验证:确保用户输入的邮箱地址符合正确的格式,例如
- 文本提取:
- 从网页中提取链接:在处理网页内容时,需要提取其中的所有链接。可以使用类似
https?://[^\s/$.?#].[^\s]*的正则表达式,它能匹配http或https开头的链接。 - 从日志文件中提取特定信息:例如,在日志文件中提取时间戳、错误代码等信息。假设日志格式为
[2023 - 01 - 01 12:00:00] INFO - Message,可以用\[\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\]来提取时间戳部分。
- 从网页中提取链接:在处理网页内容时,需要提取其中的所有链接。可以使用类似
- 文本替换:
- 格式化文本:将文本中的日期格式从
MM/dd/yyyy替换为yyyy - MM - dd。可以使用正则表达式(\d{2})/(\d{2})/(\d{4})来匹配原日期格式,并通过替换操作将其转换为新的格式。 - 屏蔽敏感信息:在处理用户数据时,可能需要屏蔽敏感信息,如电话号码中的部分数字。可以用
(\d{3})\d{4}(\d{4})匹配电话号码,并将中间四位数字替换为****,得到类似123****5678的结果。
- 格式化文本:将文本中的日期格式从
- 搜索过滤:
- 在文档中搜索特定模式:在大量的文档中搜索包含特定关键词或模式的段落。例如,在一篇技术文档中搜索所有包含
TODO:标记的行,使用^TODO:.*的正则表达式,其中^TODO:表示以TODO:开头,.*表示任意字符(包括换行符)。 - 筛选文件列表:在处理文件系统中的文件列表时,可以使用正则表达式来筛选符合特定命名模式的文件。例如,筛选出所有以
report_开头,以.txt结尾的文件,可以用^report_.*\.txt$。
- 在文档中搜索特定模式:在大量的文档中搜索包含特定关键词或模式的段落。例如,在一篇技术文档中搜索所有包含
- 词法分析:
- 编程语言解析:在编译器或解释器中,正则表达式用于将输入的代码分解成一个个词法单元(token)。例如,在解析 C# 代码时,使用正则表达式来识别关键字(如
if、else)、标识符(变量名、函数名)、运算符(如+、-)等。 - 标记语言解析:对于标记语言(如 HTML、XML),正则表达式可用于解析标签、属性等。例如,在解析 HTML 时,用
<([a-zA-Z]+)(?:\s+[a-zA - Z0 - 9_-]+="[^"]*")*>来匹配标签及其属性。
- 编程语言解析:在编译器或解释器中,正则表达式用于将输入的代码分解成一个个词法单元(token)。例如,在解析 C# 代码时,使用正则表达式来识别关键字(如
三、常见正则符号含义
- 字符类:
[abc]:匹配方括号内的任意一个字符,即a、b或c。例如,[123]可以匹配1、2或3。[a - z]:匹配小写字母范围内的任意一个字符。例如,[a - f]可以匹配a到f之间的任意一个小写字母。[^abc]:匹配除了方括号内字符之外的任意一个字符。例如,[^0 - 9]可以匹配除数字之外的任意字符。
- 预定义字符类:
\d:匹配任意一个数字字符,等价于[0 - 9]。例如,\d{3}可以匹配三个连续的数字。\D:匹配任意一个非数字字符,等价于[^0 - 9]。\w:匹配任意一个字母、数字或下划线字符,等价于[a - zA - Z0 - 9_]。例如,\w+可以匹配一个或多个由字母、数字或下划线组成的单词。\W:匹配任意一个非字母、数字或下划线字符,等价于[^a - zA - Z0 - 9_]。\s:匹配任意一个空白字符(空格、制表符、换行符等),等价于[\f\n\r\t\v]。例如,\s+可以匹配一个或多个连续的空白字符。\S:匹配任意一个非空白字符,等价于[^ \f\n\r\t\v]。
- 限定符:
*:匹配前面的元素零次或多次。例如,a*可以匹配空字符串、a、aa、aaa等。+:匹配前面的元素一次或多次。例如,a+可以匹配a、aa、aaa等,但不能匹配空字符串。?:匹配前面的元素零次或一次。例如,a?可以匹配空字符串或a。{n}:匹配前面的元素恰好n次。例如,a{3}只能匹配aaa。{n,}:匹配前面的元素至少n次。例如,a{3,}可以匹配aaa、aaaa、aaaaa等。{n,m}:匹配前面的元素至少n次,最多m次。例如,a{3,5}可以匹配aaa、aaaa、aaaaa。
- 分组与捕获:
(pattern):将pattern作为一个分组,用于捕获匹配的文本。例如,对于模式(\d{3})-(\d{3})-(\d{4})匹配电话号码123 - 456 - 7890,可以通过Match.Groups[1]获取第一个\d{3}匹配的123,Match.Groups[2]获取456,Match.Groups[3]获取7890。(?:pattern):将pattern作为一个非捕获分组。它用于分组但不捕获匹配的文本,这样可以避免在Match.Groups中产生额外的捕获组。例如,(?:a|b)+匹配a或b的一次或多次出现,但不会在Match.Groups中创建捕获组。
- 边界匹配:
^:匹配字符串的开头。例如,^Hello可以匹配以Hello开头的字符串。$:匹配字符串的结尾。例如,World$可以匹配以World结尾的字符串。\b:匹配单词边界,即单词与非单词字符的边界。例如,\bHello\b可以匹配独立的Hello单词,而不会匹配HelloWorld中的Hello。\B:匹配非单词边界。例如,\BHello\B可以匹配HelloWorld中Hello部分(因为Hello前后都不是单词边界)。
- 转义字符:
\:用于转义特殊字符,使它们失去特殊含义,仅表示其字面意思。例如,\.表示匹配一个点号,因为点号在正则表达式中有特殊含义(匹配任意字符)。同样,\*表示匹配一个星号。
四、详细案例代码
- 验证邮箱地址
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string email = "test.user123@example - domain.com";
string pattern = @"^[a-zA-Z0 - 9_.+-]+@[a-zA-Z0 - 9 -]+\.[a-zA-Z0 - 9-.]+$";
bool isValid = Regex.IsMatch(email, pattern);
Console.WriteLine($"Email {email} is valid: {isValid}");
}
}
解释:
^表示匹配字符串的开头。[a-zA-Z0 - 9_.+-]+:匹配一个或多个字母、数字、下划线、点、加号或减号,这是邮箱用户名部分。@:匹配邮箱地址中的@符号。[a-zA-Z0 - 9 -]+:匹配域名部分,由字母、数字和短横线组成。\.:转义后的点号,匹配实际的点号。[a-zA-Z0 - 9-.]+:匹配顶级域名部分,由字母、数字、短横线和点号组成。$:表示匹配字符串的结束。
- 提取 URL 链接
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string text = "Check out these links: https://www.example.com, http://another - site.net, ftp://ftp.example.org";
string pattern = @"https?://[^\s/$.?#].[^\s]*";
MatchCollection matches = Regex.Matches(text, pattern);
foreach (Match match in matches)
{
Console.WriteLine(match.Value);
}
}
}
解释:
https?:?表示?前面的s是可选的,即匹配http或https。://:匹配协议与域名之间的分隔符。[^\s/$.?#]:匹配一个非空白字符且不是/、$、.、?、#的字符,这是域名的起始字符。[^\s]*:匹配任意数量的非空白字符,用于匹配域名和路径部分。
- 替换文本中的电话号码
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string text = "Contact me at 123 - 456 - 7890 or 555 - 123 - 4567";
string pattern = @"\d{3}-\d{3}-\d{4}";
string replacement = "(***)-***-****";
string newText = Regex.Replace(text, pattern, replacement);
Console.WriteLine(newText);
}
}
解释:
\d{3}:匹配三个连续的数字。-\d{3}:匹配一个短横线和三个连续的数字。-\d{4}:匹配一个短横线和四个连续的数字。Regex.Replace方法将匹配到的电话号码格式替换为(***)-***-****。
- 搜索日志文件中的错误信息
using System;
using System.IO;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string logFile = "app.log";
string pattern = @"ERROR:\s.*";
try
{
string[] lines = File.ReadAllLines(logFile);
foreach (string line in lines)
{
if (Regex.IsMatch(line, pattern))
{
Console.WriteLine(line);
}
}
}
catch (IOException e)
{
Console.WriteLine($"Error reading file: {e.Message}");
}
}
}
解释:
ERROR::匹配ERROR:字符串。\s:匹配一个空白字符(通常是空格)。.*:匹配任意字符(包括换行符)零次或多次,用于匹配错误信息的具体内容。
- 提取 HTML 标签内的文本
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string html = "<p>Hello, World!</p><div>Some content</div><span>Another text</span>";
string pattern = @">(.*?)<";
MatchCollection matches = Regex.Matches(html, pattern);
foreach (Match match in matches)
{
Console.WriteLine(match.Groups[1].Value);
}
}
}
解释:
>:匹配 HTML 标签的结束符号。(.*?):这是一个非贪婪捕获组。.*表示匹配任意字符零次或多次,?表示非贪婪模式,即尽可能少地匹配字符,以找到第一个>和<之间的内容。<:匹配 HTML 标签的开始符号。- 通过
Match.Groups[1].Value获取捕获组中匹配的文本,即 HTML 标签内的文本内容。

888

被折叠的 条评论
为什么被折叠?



