.NET正则表达式使用指南
1. 反斜杠数字序列的特殊处理
在正则表达式中,当遇到反斜杠数字序列时,反向引用和八进制转义之间的歧义会倾向于反向引用,即便这意味着要忽略一些尾随数字。例如,对于
(\d+)\10
,
\10
会被当作对第一个捕获组的反向引用,后面接着一个字面字符
0
。
2. .NET正则表达式概述
.NET正则表达式功能强大、简洁,通过完整且易用的类接口提供支持。不过,相关文档却差强人意,存在内容不完整、编写欠佳、组织混乱甚至有误等问题。
3. 快速入门
任何使用正则表达式库的程序,都需要在文件开头添加如下代码:
Imports System.Text.RegularExpressions
以下示例均基于
String
类型的变量
TestStr
进行操作。
3.1 检查字符串是否匹配
If Regex.IsMatch(TestStr, "^\s+$")
Console.WriteLine("line is empty")
Else
Console.WriteLine("line is not empty")
End If
使用匹配选项的示例:
If Regex.IsMatch(TestStr, "^subject:", RegexOptions.IgnoreCase)
Console.WriteLine("line is a subject line")
Else
Console.WriteLine("line is not a subject line")
End If
3.2 匹配并获取匹配的文本
Dim TheNum as String = Regex.Match(TestStr, "\d+").Value
If TheNum <> ""
Console.WriteLine("Number is: " & TheNum)
End If
使用匹配选项的示例:
Dim ImgTag as String = Regex.Match(TestStr, "<img\b[^>]+>", RegexOptions.IgnoreCase).Value
If ImgTag <> ""
Console.WriteLine("Image tag: " & ImgTag)
End If
3.3 匹配并获取捕获的文本
获取第一个捕获组(如
$1
)作为字符串:
Dim Subject as String = Regex.Match(TestStr, "^Subject: (.+)").Groups(1).Value
If Subject <> ""
Console.WriteLine("Subject is: " & Subject)
End If
注意,C# 中使用
Groups[1]
而非
Groups(1)
。
使用匹配选项的示例:
Dim Subject as String = Regex.Match(TestStr, "^subject: (.+)", RegexOptions.IgnoreCase).Groups(1).Value
If Subject <> ""
Console.WriteLine("Subject is: " & Subject)
End If
使用命名捕获的示例:
Dim Subject as String = Regex.Match(TestStr, "^subject: (?<Subj>.+)", RegexOptions.IgnoreCase).Groups("Subj").Value
If Subject <> ""
Console.WriteLine("Subject is: " & Subject)
End If
3.4 搜索和替换
将测试字符串转换为适合 HTML 包含的“安全”字符串,把 HTML 特殊字符转换为 HTML 实体:
TestStr = Regex.Replace(TestStr, "&", "&")
TestStr = Regex.Replace(TestStr, "<", "<")
TestStr = Regex.Replace(TestStr, ">", ">")
Console.WriteLine("Now safe in HTML: " & TestStr)
替换字符串(第三个参数)会进行特殊解释,例如,在替换字符串中,
$&
会被替换为正则表达式实际匹配的文本。
将大写单词用
<B>...</B>
包裹:
TestStr = Regex.Replace(TestStr, "\b[A-Z]\w+", "<B>$&</B>")
Console.WriteLine("Modified string: " & TestStr)
不区分大小写地将
<B>...</B>
替换为
<I>...</I>
:
TestStr = Regex.Replace(TestStr, "<b>(.+?)</b>", "<I>$1</I>", RegexOptions.IgnoreCase)
Console.WriteLine("Modified string: " & TestStr)
4. 包概述
通过使用.NET正则表达式丰富便捷的类结构,能充分发挥其优势。以下是一个完整的控制台应用程序示例,展示了如何使用显式对象进行简单匹配:
Option Explicit On ' 这些并非使用正则表达式的必需项,但属于良好的通用实践。
Option Strict On
' 使与正则表达式相关的类易于使用。
Imports System.Text.RegularExpressions
Module SimpleTest
Sub Main()
Dim SampleText as String = "this is the 1st test string"
Dim R as Regex = New Regex("\d+\w+") ' 编译模式。
Dim M as Match = R.Match(SampleText) ' 与字符串进行匹配检查。
If not M.Success
Console.WriteLine("no match")
Else
Dim MatchedText as String = M.Value ' 查询结果...
Dim MatchedFrom as Integer = M.Index
Dim MatchedLen as Integer = M.Length
Console.WriteLine("matched [" & MatchedText & "]" &
" from char#" & MatchedFrom.ToString() &
" for " & MatchedLen.ToString() & " chars.")
End If
End Sub
End Module
从命令行执行该程序时,会将
\d+\w+
应用于示例文本,并输出:
matched [1st] from char#12 for 3 chars.
在 VB 程序中,若要访问.NET正则表达式对象,需在程序顶部添加
Imports System.Text.RegularExpressions
语句,以便编译器能够识别。在 C# 中,对应的语句为:
using System.Text.RegularExpressions;
上述示例展示了底层原始正则表达式对象的使用。以下两行代码:
Dim R as Regex = New Regex("\d+\w+") ' 编译模式。
Dim M as Match = R.Match(SampleText) ' 与字符串进行匹配检查。
也可合并为:
Dim M as Match = Regex.Match(SampleText, "\d+\w+") ' 对字符串检查模式。
合并后的代码更易于编写,减少了程序员的输入量和需要跟踪的对象数量,但会有轻微的性能损失。
5. 核心对象概述
.NET正则表达式的功能通过七个高度交织的类提供,但实际使用中,通常只需了解其中三个核心类,下面以
\s+(\d+)
对字符串
May 16, 1998
进行重复匹配为例进行说明。
5.1 Regex对象
创建
Regex
对象的示例:
Dim R as Regex = New Regex("\s+(\d+)")
创建好
Regex
对象后,可使用其
Match(text)
方法将其应用于文本,该方法会返回首次匹配的信息:
Dim M as Match = R.Match("May 16, 1998")
5.2 Match对象
Regex
对象的
Match(...)
方法会创建并返回一个
Match
对象,该对象包含多个属性,如
Success
(布尔值,指示匹配是否成功)和
Value
(若匹配成功,为实际匹配的文本副本)。
从
Match
对象获取捕获括号内匹配文本的方法有两种:一是通过索引访问
Match
对象的
Groups
属性,如
Groups(1).Value
可获取类似于 Perl 中
$1
的值(在 C# 中使用
Groups[1].Value
);二是使用
Result
方法。
5.3 Group对象
Groups(1)
实际上引用的是一个
Group
对象,后续的
.Value
引用的是该对象的
Value
属性(即与该组相关联的文本)。每个捕获括号对应一个
Group
对象,还有一个编号为零的“虚拟组”,用于保存整个匹配的信息。因此,
MatchObj.Value
和
MatchObj.Groups(0).Value
是相同的,使用前者更为简洁方便,但了解零组也很重要,因为
MatchObj.Groups.Count
包含了它。对于
\s+(\d+)
的成功匹配,
MatchObj.Groups.Count
的值为 2(整个匹配的“零组”和
$1
组)。
5.4 Capture对象
还有一个
Capture
对象,但使用频率较低。
当正则表达式应用于字符串并生成
Match
对象时,所有匹配结果(如匹配位置、每个捕获组匹配的内容等)都会被计算并封装到
Match
对象中。访问
Match
对象及其
Group
对象的属性和方法,只是获取已经计算好的结果。
6. 核心对象详细介绍
6.1 创建Regex对象
创建
Regex
对象的构造函数较为简单,可接受一个参数(正则表达式字符串)或两个参数(正则表达式和一组选项)。
单参数示例:
Dim StripTrailWS = new Regex("\s+$") ' 用于去除尾随空格
双参数示例:
Dim GetSubject = new Regex("^subject: (.+)", RegexOptions.IgnoreCase)
若需要传递多个选项标志,可使用按位或运算符
OR
进行组合:
Dim GetSubject = new Regex("^subject: (.+)", RegexOptions.IgnoreCase OR RegexOptions.Multiline)
6.2 异常处理
如果提供的正则表达式包含无效的元字符组合,会抛出
ArgumentException
错误。在使用已知有效的正则表达式时,通常无需捕获此异常,但如果使用来自程序外部(如用户输入或配置文件读取)的正则表达式,捕获该异常就很重要。示例如下:
Dim R As Regex
Try
R = New Regex(SearchRegex)
Catch e As ArgumentException
Console.WriteLine("+ERROR+ bad regex: " & e.ToString)
Exit Sub
End Try
6.3 Regex选项
创建
Regex
对象时,允许使用以下选项标志:
| 选项标志 | 说明 |
| — | — |
|
RegexOptions.IgnoreCase
| 应用正则表达式时不区分大小写。 |
|
RegexOptions.IgnorePatternWhitespace
| 以自由间距和注释模式解析正则表达式。使用
#...
注释时,需在每个逻辑行末尾添加换行符,否则第一个注释会注释掉整个正则表达式的其余部分。在 VB.NET 中,可使用
(?#...)
注释更方便。 |
|
RegexOptions.Multiline
| 以增强的行锚定模式应用正则表达式,允许
^
和
$
分别在嵌入的换行符处匹配,而不仅仅是字符串的开头和结尾。 |
|
RegexOptions.Singleline
| 以点匹配所有模式应用正则表达式,允许点
.
匹配任何字符,而不仅仅是除换行符之外的字符。 |
|
RegexOptions.ExplicitCapture
| 即使是普通的
(...)
括号,通常为捕获括号,也不会进行捕获,而是像
(?:...)
分组非捕获括号一样工作。这样,只有命名捕获
(?<name>...)
括号会进行捕获。 |
|
RegexOptions.RightToLeft
| 将正则表达式设置为从右到左的匹配模式。 |
|
RegexOptions.Compiled
| 即时将正则表达式编译为高度优化的格式,通常可显著提高匹配速度,但会增加首次使用时的编译时间和程序运行期间的内存使用。如果正则表达式仅使用一次或很少使用,使用此选项意义不大;但如果在时间关键区域使用,可能会带来优势。 |
|
RegexOptions.ECMAScript
| 以与 ECMAScript 兼容的方式解析正则表达式。如果不了解 ECMAScript 或不需要与之兼容,可忽略此选项。 |
|
RegexOptions.None
| 这是一个“无额外选项”的值,用于初始化
RegexOptions
变量,后续可根据需要按位或运算添加其他选项。 |
6.4 使用Regex对象
拥有正则表达式对象后,需将其应用于文本才能发挥作用,以下是相关方法:
-
RegexObj.IsMatch(target)
和
RegexObj.IsMatch(target, offset)
:返回类型为
Boolean
,用于判断对象的正则表达式是否与目标字符串匹配。若提供
offset
(整数),则在目标字符串中跳过相应数量的字符后再开始匹配。示例:
Dim R as Regex = New Regex("^\s+$")
If R.IsMatch(Line) Then
' Line 为空...
End If
-
RegexObj.Match(target)、RegexObj.Match(target, offset)和RegexObj.Match(target, offset, maxlength):返回类型为Match对象,用于将对象的正则表达式应用于目标字符串,并返回一个Match对象,通过该对象可查询匹配结果的相关信息。若提供offset,会跳过相应数量的字符后开始匹配;若提供maxlength,匹配会进入特殊模式,正则表达式引擎会将从offset开始的maxlength个字符视为整个目标字符串,引擎会忽略该范围之外的字符。示例如下表所示:
| 方法调用 |\d\d|^\d\d|^\d\d$|
| — | — | — | — |
|RegexObj.Match("May 16, 1998")| 匹配16| 失败 | 失败 |
|RegexObj.Match("May 16, 1998", 9)| 匹配99| 失败 | 失败 |
|RegexObj.Match("May 16, 1998", 9, 2)| 匹配99| 匹配99| 匹配99| -
RegexObj.Matches(target)和RegexObj.Matches(target, offset):返回类型为MatchCollection,与Match方法类似,但会返回一个表示目标字符串中所有匹配项的Match对象集合。示例:
Dim R as New Regex("\w+")
Dim Target as String = "a few words"
Dim BunchOfMatches as MatchCollection = R.Matches(Target)
Dim I as Integer
For I = 0 to BunchOfMatches.Count - 1
Dim MatchObj as Match = BunchOfMatches.Item(I)
Console.WriteLine("Match: " & MatchObj.Value)
Next
也可省略
MatchCollection
对象:
Dim MatchObj as Match
For Each MatchObj in R.Matches(Target)
Console.WriteLine("Match: " & MatchObj.Value)
Next
还可使用
Match
方法实现相同功能:
Dim MatchObj as Match = R.Match(Target)
While MatchObj.Success
Console.WriteLine("Match: " & MatchObj.Value)
MatchObj = MatchObj.NextMatch()
End While
-
RegexObj.Replace(target, replacement)、RegexObj.Replace(target, replacement, count)和RegexObj.Replace(target, replacement, count, offset):返回类型为String,用于在目标字符串中进行搜索和替换操作。replacement参数可以是字符串或MatchEvaluator委托。若提供count,则只进行指定次数的替换(默认替换所有匹配项);若提供offset,会跳过相应数量的字符后再应用正则表达式。示例:
Dim RRCapWord as New Regex("\b[A-Z]\w+")
Text = RRCapWord.Replace(Text, "<B>$0</B>") ' 将大写单词用 <B>...</B> 包裹
Dim AnyWS as New Regex("\s+")
Target = AnyWS.Replace(Target, " ") ' 规范所有空白字符
Dim AnyWS as New Regex("\s+")
Dim LeadingWS as New Regex("^\s+")
Target = AnyWS.Replace(Target, " ", -1, LeadingWS.Match(Target).Length) ' 保留前导空白字符
综上所述,通过对.NET正则表达式核心对象和方法的详细介绍,我们了解了如何创建、配置和使用正则表达式对象进行字符串匹配、捕获和替换操作。合理运用这些功能,能在处理文本数据时提高效率和准确性。
下面通过一个 mermaid 流程图展示使用
Regex
对象进行匹配的基本流程:
graph TD;
A[创建 Regex 对象] --> B[应用 Match 方法];
B --> C{匹配是否成功};
C -- 是 --> D[获取匹配信息];
C -- 否 --> E[输出无匹配信息];
这个流程图清晰地展示了使用
Regex
对象进行匹配的主要步骤,从创建对象开始,到应用匹配方法,再根据匹配结果进行不同的处理。
7. 替换字符串的特殊解释
在使用
RegexObj.Replace
方法时,替换字符串(第三个参数)会进行特殊解释。以下是一些常见的特殊替换语法:
-
$&
:会被替换为正则表达式实际匹配的文本。例如:
TestStr = Regex.Replace(TestStr, "\b[A-Z]\w+", "<B>$&</B>")
此代码会将所有以大写字母开头的单词用
<B>...</B>
包裹。
-
$n
:其中
n
是一个数字,表示捕获组的编号。
$1
代表第一个捕获组匹配的文本,
$2
代表第二个捕获组匹配的文本,以此类推。例如:
TestStr = Regex.Replace(TestStr, "<b>(.+?)</b>", "<I>$1</I>", RegexOptions.IgnoreCase)
该代码会不区分大小写地将
<B>...</B>
标签替换为
<I>...</I>
标签,
$1
会被替换为
<b>
和
</b>
之间的文本。
8. 实际应用场景示例
8.1 验证用户输入
在开发应用程序时,经常需要验证用户输入的格式是否正确。例如,验证用户输入的邮箱地址是否合法:
Dim emailRegex as New Regex("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
Dim userInput as String = "test@example.com"
If emailRegex.IsMatch(userInput) Then
Console.WriteLine("Valid email address")
Else
Console.WriteLine("Invalid email address")
End If
上述代码使用正则表达式验证用户输入的字符串是否符合邮箱地址的格式。
8.2 数据提取
从文本中提取特定的数据也是正则表达式的常见应用场景。例如,从一段 HTML 代码中提取所有图片标签:
Dim html as String = "<html><body><img src='image1.jpg'><p>Some text</p><img src='image2.jpg'></body></html>"
Dim imgRegex as New Regex("<img\b[^>]+>")
Dim matches as MatchCollection = imgRegex.Matches(html)
For Each match as Match in matches
Console.WriteLine("Image tag: " & match.Value)
Next
该代码会找出 HTML 代码中所有的
<img>
标签并输出。
8.3 文本清理
在处理文本数据时,可能需要清理一些不必要的字符或格式。例如,去除文本中的所有 HTML 标签:
Dim htmlText as String = "<p>Some <b>bold</b> text</p>"
Dim tagRegex as New Regex("<[^>]+>")
Dim cleanText as String = tagRegex.Replace(htmlText, "")
Console.WriteLine("Clean text: " & cleanText)
此代码会将文本中的所有 HTML 标签替换为空字符串,从而得到清理后的纯文本。
9. 性能考虑
在使用.NET 正则表达式时,性能是一个需要考虑的重要因素。以下是一些性能优化的建议:
-
使用
RegexOptions.Compiled
:如果正则表达式会被多次使用,建议使用
RegexOptions.Compiled
选项将其编译为高度优化的格式,这样可以显著提高匹配速度。但如果正则表达式只使用一次或很少使用,使用该选项会增加编译时间和内存使用,反而不利于性能。例如:
Dim compiledRegex as New Regex("\d+\w+", RegexOptions.Compiled)
-
避免不必要的回溯
:正则表达式中的回溯会导致性能下降。尽量使用更精确的模式,避免使用过于宽泛的量词和复杂的嵌套结构。例如,使用
\d{3}代替\d+来匹配三位数字,这样可以减少回溯的可能性。 -
缓存
Regex对象 :如果在程序中多次使用相同的正则表达式,建议将Regex对象缓存起来,避免重复创建,从而提高性能。例如:
Public Class RegexCache
Private Shared regexCache as New Dictionary(Of String, Regex)()
Public Shared Function GetRegex(pattern as String) as Regex
If Not regexCache.ContainsKey(pattern) Then
regexCache(pattern) = New Regex(pattern)
End If
Return regexCache(pattern)
End Function
End Class
' 使用缓存的 Regex 对象
Dim cachedRegex as Regex = RegexCache.GetRegex("\d+\w+")
10. 总结
.NET 正则表达式是一个强大的工具,通过丰富的类接口和灵活的选项,可以实现复杂的字符串匹配、捕获和替换操作。在实际应用中,我们可以根据不同的需求选择合适的方法和选项,同时注意性能优化,以提高程序的效率和准确性。
下面通过一个 mermaid 流程图总结使用.NET 正则表达式的一般流程:
graph LR;
A[确定需求] --> B[编写正则表达式];
B --> C{是否需要选项};
C -- 是 --> D[选择合适的 RegexOptions];
C -- 否 --> E[创建 Regex 对象];
D --> E;
E --> F{选择操作类型};
F -- 匹配 --> G[使用 Match 或 Matches 方法];
F -- 替换 --> H[使用 Replace 方法];
F -- 验证 --> I[使用 IsMatch 方法];
G --> J[处理匹配结果];
H --> K[获取替换后的字符串];
I --> L[输出验证结果];
这个流程图展示了从确定需求到最终处理结果的整个过程,涵盖了使用.NET 正则表达式的主要步骤。通过合理运用这些步骤和方法,我们可以更好地利用.NET 正则表达式来解决各种文本处理问题。
总之,掌握.NET 正则表达式的使用方法和技巧,对于处理文本数据、验证用户输入等任务具有重要意义。希望通过本文的介绍,能帮助大家更深入地理解和应用.NET 正则表达式。
超级会员免费看
1936

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



