ZetCode

C# 正则表达式

上次修改时间:2025 年 5 月 18 日

C# 正则表达式教程展示了如何在 C# 中使用正则表达式解析文本。

正则表达式是强大的工具,用于文本搜索、验证和高级字符串操作。 它们提供了一种灵活的方式来匹配和处理文本中的模式。 正则表达式通常用于诸如 grepsed 之类的工具、诸如 viEmacs 之类的文本编辑器以及包括 C#JavaPerl 在内的编程语言。

C# 通过 System.Text.RegularExpressions 命名空间提供了一个内置的 API 来处理正则表达式。 此命名空间包含 Regex 类,该类提供了强大的方法来有效地处理字符串模式。

C# 中的 Regex 类定义了不可变的正则表达式,并提供了以下方法:

通过利用 C# 中的正则表达式,开发人员可以使用最少的代码有效地解析、验证和转换文本数据。 了解模式语法和内置的正则表达式方法可以更有效地进行字符串处理。

Regex 示例

下表显示了一些正则表达式字符串。

Regex 含义
. 匹配任何单个字符。
? 匹配前一个元素一次或不匹配。
+ 匹配前一个元素一次或多次。
* 匹配前一个元素零次或多次。
^ 匹配字符串内的起始位置。
$ 匹配字符串内的结束位置。
| 交替运算符。
[abc] 匹配 a、b 或 c。
[a-c] 范围;匹配 a、b 或 c。
[^abc] 否定;匹配除 a、b 或 c 之外的所有字符。
\s 匹配空白字符。
\w 匹配单词字符;等同于 [a-zA-Z_0-9]

C# regex isMatch

isMatch 方法指示正则表达式是否在输入字符串中找到匹配项。

Program.cs
using System.Text.RegularExpressions;

List<string> words = [ "Seven", "even",
    "Maven", "Amen", "eleven" ];

var rx = new Regex(@".even", RegexOptions.Compiled);

foreach (string word in words)
{
    if (rx.IsMatch(word))
    {
        Console.WriteLine($"{word} does match");
    }
    else
    {
        Console.WriteLine($"{word} does not match");
    }
}

在此示例中,我们在列表中有五个单词。 我们检查哪些单词与 .even 正则表达式匹配。

var words = new List<string>() { "Seven", "even",
        "Maven", "Amen", "eleven" };

我们有一系列单词。

var rx = new Regex(@".even", RegexOptions.Compiled);

我们定义 .even 正则表达式。 RegexOptions.Compiled 选项指定将正则表达式编译为程序集。 这可以加快执行速度,但会增加启动时间。 点 (.) 元字符代表文本中的任何单个字符。

foreach (string word in words)
{
    if (rx.IsMatch(word))
    {
        Console.WriteLine($"{word} does match");
    }
    else
    {
        Console.WriteLine($"{word} does not match");
    }
}

我们遍历单词列表。 如果单词与正则表达式匹配,则 IsMatch 方法返回 true。

$ dotnet run
Seven does match
even does not match
Maven does not match
Amen does not match
eleven does match

C# regex Match index

MatchSuccess 属性返回一个布尔值,指示匹配是否成功。 NextMatch 方法返回一个新的 Match 对象,其中包含下一个匹配项的结果,从上次匹配结束的位置开始。

我们可以使用 MatchIndex 属性查找字符串中匹配项的位置。

Program.cs
using System.Text.RegularExpressions;

var content = @"Foxes are omnivorous mammals belonging to several genera
of the family Canidae. Foxes have a flattened skull, upright triangular ears,
a pointed, slightly upturned snout, and a long bushy tail. Foxes live on every
continent except Antarctica. By far the most common and widespread species of
fox is the red fox.";

var rx = new Regex("fox(es)?", RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

Match match = rx.Match(content);

while (match.Success)
{
    Console.WriteLine($"{match.Value} at index {match.Index}");
    match = match.NextMatch();
}

在该示例中,我们查找 fox 单词的所有出现项。

var rx = new Regex("fox(es)?", RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

我们添加 (es)? 表达式以包括单词的复数形式。 RegexOptions.IgnoreCase 在不区分大小写的模式下搜索。

Match match = rx.Match(content);

while (match.Success)
{
    Console.WriteLine($"{match.Value} at index {match.Index}");
    match = match.NextMatch();
}

match.Value 返回匹配的字符串,而 match.Index 返回其在文本中的索引。 我们使用 match.NextMatch 方法查找匹配项的下一个出现项。

$ dotnet run
Foxes at index 0
Foxes at index 80
Foxes at index 194
fox at index 292
fox at index 307

C# regex Matches

Matches 方法搜索输入字符串中正则表达式的所有出现项,并返回所有匹配项。

Program.cs
using System.Text.RegularExpressions;

String content = @"<p>The <code>Regex</code> is a compiled 
                representation of a regular expression.</p>";

var rx = new Regex(@"</?[a-z]+>", RegexOptions.Compiled);
var matches = rx.Matches(content);

foreach (Match match in matches)
{
    Console.WriteLine(match);
}

该示例从字符串中检索所有 HTML 标签。

var rx = new Regex(@"</?[a-z]+>", RegexOptions.Compiled);

在正则表达式中,我们搜索标签;包括开始标签和结束标签。

var matches = rx.Matches(content);

Matches 方法返回搜索找到的 Match 对象的集合。 如果未找到任何匹配项,则该方法返回一个空集合对象。

foreach (Match match in matches)
{
    Console.WriteLine(match);
}

我们遍历该集合并打印所有匹配的字符串。

$ dotnet run
<p>
<code>
</code>
</p>

C# regex Count

使用 Count,我们可以计算模式出现的次数。 我们具有该方法的静态重载和实例重载。

Program.cs
using System.Text.RegularExpressions;

string content = @"Foxes are omnivorous mammals belonging to several genera
of the family Canidae. Foxes have a flattened skull, upright triangular ears,
a pointed, slightly upturned snout, and a long bushy tail. Foxes live on every
continent except Antarctica. By far the most common and widespread species of
fox is the red fox.";

string pattern = "fox(es)?";

int n = Regex.Count(content, pattern, RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

Console.WriteLine($"There are {n} matches");

在该程序中,我们计算 fox 单词的变体的数量。

int n = Regex.Count(content, pattern, RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

我们使用静态 Regex.Count 方法。


var rx = new Regex(pattern, RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

int n = rx.Count(content);

Console.WriteLine($"There are {n} matches");

我们还可以使用实例方法。

$ dotnet run
There are 5 matches

C# regex 单词边界

元字符 \b 是一个锚点,它匹配一个称为单词边界的位置。它允许搜索整个单词。

Program.cs
using System.Text.RegularExpressions;

var text = "This island is beautiful";

var rx = new Regex(@"\bis\b", RegexOptions.Compiled);
var matches = rx.Matches(text);

foreach (Match match in matches)
{
    Console.WriteLine($"{match.Value} at {match.Index}");
}

在该示例中,我们查找 is 单词。 我们不想包括 Thisisland 单词。

var rx = new Regex(@"\bis\b", RegexOptions.Compiled);

使用两个 \b 元字符,我们搜索 is 整个单词。

$ dotnet run
is at 12

C# regex 隐式单词边界

\w 是一个字符类,用于单词中允许的字符。 对于 \w+ 正则表达式(表示一个单词),前导和尾随单词边界元字符是隐式的;即 \w+ 等于 \b\w+\b

Program.cs
using System.Text.RegularExpressions;

var content = @"Foxes are omnivorous mammals belonging to several genera 
of the family Canidae. Foxes have a flattened skull, upright triangular ears, 
a pointed, slightly upturned snout, and a long bushy tail. Foxes live on every 
continent except Antarctica. By far the most common and widespread species of 
fox is the red fox.";

var rx = new Regex(@"\w+", RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

var matches = rx.Matches(content);
Console.WriteLine(matches.Count);

foreach (var match in matches)
{
    Console.WriteLine(match);
}

在该示例中,我们搜索文本中的所有单词。

Console.WriteLine(matches.Count);

Count 属性返回匹配项的数量。

C# regex 货币符号

\p{Sc} 正则表达式可用于查找货币符号。

Program.cs
using System.Text.RegularExpressions;

Console.OutputEncoding = System.Text.Encoding.UTF8;

string content = @"Currency symbols: ฿ Thailand bath, ₹  Indian rupee, 
    ₾ Georgian lari, $ Dollar, € Euro, ¥ Yen, £ Pound Sterling";

string pattern = @"\p{Sc}";

var rx = new Regex(pattern, RegexOptions.Compiled);
var matches = rx.Matches(content);

foreach (Match match in matches)
{
    Console.WriteLine($"{match.Value} is at {match.Index}");
}

在该示例中,我们查找货币符号。

string content = @"Currency symbols: ฿ Thailand bath, ₹ Indian rupee, 
    ₾ Georgian lari, $ Dollar, € Euro, ¥ Yen, £ Pound Sterling";

文本中有几个货币符号。

string pattern = @"\p{Sc}";

我们定义货币符号的正则表达式。

foreach (Match match in matches)
{
    Console.WriteLine($"{match.Value} is at {match.Index}");
}

我们查找所有符号及其索引。

$ dotnet run 
฿ is at 18
₹  is at 35
₾ is at 57
$ is at 74
€ is at 84
¥ is at 92
£ is at 99

C# regex 锚点

锚点匹配给定文本中字符的位置。在下一个示例中,我们查看一个字符串是否位于句子的开头。

Program.cs
using System.Text.RegularExpressions;

List<string> sentences = [
    "I am looking for Jane.",
    "Jane was walking along the river.",
    "Kate and Jane are close friends."
];

var rx = new Regex(@"^Jane", RegexOptions.Compiled);

foreach (string sentence in sentences)
{
    if (rx.IsMatch(sentence))
    {
        Console.WriteLine($"{sentence} does match");
    }
    else
    {
        Console.WriteLine($"{sentence} does not match");
    }
}

我们有三个句子。搜索模式是 ^Jane。该模式检查 "Jane" 字符串是否位于文本的开头。Jane\.$ 将查找句子末尾的 "Jane"。

C# regex 交替选择

交替运算符 | 使能够创建具有多个选项的正则表达式。

Program.cs
using System.Text.RegularExpressions;

List<string> users = ["Jane", "Thomas", "Robert",
    "Lucy", "Beky", "John", "Peter", "Andy"];

var rx = new Regex("Jane|Beky|Robert", RegexOptions.Compiled);

foreach (string user in users)
{
    if (rx.IsMatch(user))
    {
        Console.WriteLine($"{user} does match");
    }
    else
    {
        Console.WriteLine($"{user} does not match");
    }
}

列表中有九个名字。

var rx = new Regex("Jane|Beky|Robert", RegexOptions.Compiled);

这个正则表达式查找 "Jane"、"Beky" 或 "Robert" 字符串。

C# regex 捕获组

圆括号 用于创建捕获组。 这使我们可以将量词应用于整个组,或者将交替选择限制为正则表达式的一部分。

Program.cs
using System.Text.RegularExpressions;

List<string> sites = ["webcode.me", "zetcode.com",
    "freebsd.org", "netbsd.org"];

var rx = new Regex(@"(\w+)\.(\w+)", RegexOptions.Compiled);

foreach (var site in sites)
{
    Match match = rx.Match(site);

    if (match.Success)
    {
        Console.WriteLine(match.Value);
        Console.WriteLine(match.Groups[1]);
        Console.WriteLine(match.Groups[2]);
    }

    Console.WriteLine("*****************");
}

在示例中,我们使用组将域名分成两部分。

var rx = new Regex(@"(\w+)\.(\w+)", RegexOptions.Compiled);

我们用括号定义了两个组。

if (match.Success)
{
    Console.WriteLine(match.Value);
    Console.WriteLine(match.Groups[1]);
    Console.WriteLine(match.Groups[2]);
}

match.Value 返回整个匹配的字符串;它等于 match.Groups[0]。 这些组通过 Groups 属性访问。

$ dotnet run
webcode.me
webcode
me
*****************
zetcode.com
zetcode
com
*****************
freebsd.org
freebsd
org
*****************
netbsd.org
netbsd
org
*****************

在以下示例中,我们使用组来处理表达式。

Program.cs
using System.Text.RegularExpressions;

string[] expressions = ["16 + 11", "12 * 5", "27 / 3", "2 - 8"];
string pattern = @"(\d+)\s+([-+*/])\s+(\d+)";

foreach (var expression in expressions)
{
    var rx = new Regex(pattern, RegexOptions.Compiled);
    var matches = rx.Matches(expression);

    foreach (Match match in matches)
    {
        int val1 = int.Parse(match.Groups[1].Value);
        int val2 = int.Parse(match.Groups[3].Value);

        var oper = match.Groups[2].Value;

        string result = oper switch
        {
            "+" => $"{match.Value} = {val1 + val2}",
            "-" => $"{match.Value} = {val1 - val2}",
            "*" => $"{match.Value} = {val1 * val2}",
            "/" => $"{match.Value} = {val1 / val2}",
            _ => "unknown operator"
        };

        Console.WriteLine(result);
    }
}

该示例解析四个简单的数学表达式并对其进行计算。

string[] expressions = ["16 + 11", "12 * 5", "27 / 3", "2 - 8"];

我们有一个包含四个表达式的数组。

string pattern = @"(\d+)\s+([-+*/])\s+(\d+)";

在正则表达式模式中,我们有三个组:两个组用于值,一个组用于运算符。

int val1 = int.Parse(match.Groups[1].Value);
int val2 = int.Parse(match.Groups[3].Value);

我们获取值并将其转换为整数。

var oper = match.Groups[2].Value;

我们获取运算符。

string result = oper switch
{
    "+" => $"{match.Value} = {val1 + val2}",
    "-" => $"{match.Value} = {val1 - val2}",
    "*" => $"{match.Value} = {val1 * val2}",
    "/" => $"{match.Value} = {val1 / val2}",
    _ => "unknown operator"
};

使用 switch 表达式,我们计算表达式。

$ dotnet run
16 + 11 = 27
12 * 5 = 60
27 / 3 = 9
2 - 8 = -6

C# regex 捕获

当我们使用量词时,该组可以在单个匹配项中捕获零个、一个或多个字符串。 单个捕获组匹配的所有子字符串都可以从 Group.Captures 属性中获得。 在这种情况下,Group 对象包含有关最后捕获的子字符串的信息。

Program.cs
using System.Text.RegularExpressions;

string text = "Today is a beautiful day. The sun is shining.";
string pattern = @"\b(\w+\s*)+\.";

MatchCollection matches = Regex.Matches(text, pattern);

foreach (Match match in matches)
{
    Console.WriteLine("Matched sentence: {0}", match.Value);

    for (int i = 0; i < match.Groups.Count; i++)
    {
        Console.WriteLine("\tGroup {0}:  {1}", i, match.Groups[i].Value);

        int captures = 0;

        foreach (Capture capture in match.Groups[i].Captures)
        {
            Console.WriteLine("\t\tCapture {0}: {1}", captures, capture.Value);
            captures++;
        }
    }
}

在该示例中,我们有两个句子。 使用正则表达式,我们捕获句子中的所有单词。

string pattern = @"\b(\w+\s*)+\.";

我们将 + 量词用于 (\w+\s*) 组。 然后,该组包含所有捕获:句子的单词。

foreach (Capture capture in match.Groups[i].Captures)
{
    Console.WriteLine("\t\tCapture {0}: {1}", captures, capture.Value);
    captures++;
}

我们遍历该组的捕获并将它们打印到控制台。

$ dotnet run
Matched sentence: Today is a beautiful day.
        Group 0:  Today is a beautiful day.
                Capture 0: Today is a beautiful day.
        Group 1:  day
                Capture 0: Today
                Capture 1: is
                Capture 2: a
                Capture 3: beautiful
                Capture 4: day
Matched sentence: The sun is shining.
        Group 0:  The sun is shining.
                Capture 0: The sun is shining.
        Group 1:  shining
                Capture 0: The
                Capture 1: sun
                Capture 2: is
                Capture 3: shining

这是输出。 请记住,match.Groups[0].Value 等于 match.Value

C# regex 多行选项

RegexOptions.Multiline 选项更改正则表达式中 ^$ 锚点的行为。 启用此选项后,^ 匹配任何行的开头(而不仅仅是字符串的开头),而 $ 匹配任何行的结尾(而不仅仅是字符串的结尾)。 这在处理多行文本数据时非常有用。

Program.cs
using System.Text.RegularExpressions;

string text = "apple\nbanana\napple pie\ncherry\napple tart";

// Without Multiline: ^apple matches only at the start of the string
var rx1 = new Regex("^apple");
foreach (Match m in rx1.Matches(text))
{
    Console.WriteLine($"Without Multiline: {m.Value} at {m.Index}");
}

// With Multiline: ^apple matches at the start of any line
var rx2 = new Regex("^apple", RegexOptions.Multiline);
foreach (Match m in rx2.Matches(text))
{
    Console.WriteLine($"With Multiline: {m.Value} at {m.Index}");
}

在本例中,当未设置 RegexOptions.Multiline 时,^apple 仅匹配第一行。 启用该选项后,它将匹配以“apple”开头的每一行。

$ dotnet run
Without Multiline: apple at 0
With Multiline: apple at 0
With Multiline: apple at 13
With Multiline: apple at 30

C# regex 替换字符串

可以使用 Replace 替换字符串。 该方法返回修改后的字符串。

Program.cs
using System.Text.RegularExpressions;


using var client = new HttpClient();
var content = await client.GetStringAsync("https://webcode.me");

var rx = new Regex(@"<[^>]*>", RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

var modified = rx.Replace(content, String.Empty);

Console.WriteLine(modified.Trim());

该示例读取网页的 HTML 数据并使用正则表达式剥离其 HTML 标签。

using var client = new HttpClient();
var content = await client.GetStringAsync("http://webcode.me");

我们使用 HttpClient 创建一个 GET 请求并检索 HTML 代码。

var rx = new Regex(@"<[^>]*>", RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

此模式定义了一个匹配 HTML 标签的正则表达式。

var modified = rx.Replace(content, String.Empty);

我们使用 replaceAll 方法删除所有标签。

C# regex 分割文本

可以使用 Patternsplit 方法分割文本。

data.csv
22, 1, 3, 4, 5, 17, 18,
2, 13, 4, 1, 8, 4,
3, 21, 4, 5, 1, 48, 9, 42

我们从 data.csv 文件读取数据。

Program.cs
using System.Text.RegularExpressions;

string content = File.ReadAllText("data.csv");

var rx = new Regex(@",\s*", RegexOptions.Compiled);
var data = rx.Split(content);

Console.WriteLine("[{0}]", string.Join(", ", data));

int sum = 0;
Array.ForEach(data, e =>
{
    string e2 = e.Trim();

    sum += Int32.Parse(e);
});

Console.WriteLine(sum);

该示例从 CSV 文件读取值并计算它们的总和。 它使用正则表达式处理数据。

string content = File.ReadAllText("data.csv");

一次性地,我们使用 File.ReadAllText 将所有数据读取到字符串列表中。

var rx = new Regex(@",\s*", RegexOptions.Compiled);

正则表达式是一个逗号字符,后跟零个或多个空白字符。

var data = rx.Split(content);

Split 方法将输入字符串拆分为一个子字符串数组。

int sum = 0;
Array.ForEach(data, e => {

    var e2 = e.Trim();

    sum += Int32.Parse(e);
});

我们遍历这些行并使用 trim 截断空格并计算 sum 值。

$ dotnet run
[22, 1, 3, 4, 5, 17, 18, 2, 13, 4, 1, 8, 4, 3, 21, 4, 5, 1, 48, 9, 42]
235

C# 不区分大小写的正则表达式

通过设置 RegexOptions.IgnoreCase 标志,我们可以进行不区分大小写的匹配。

Program.cs
using System.Text.RegularExpressions;

List<string> words = ["dog", "Dog", "DOG", "Doggy"];

var rx = new Regex(@"\bdog\b", RegexOptions.Compiled |
    RegexOptions.IgnoreCase);

foreach (string word in words)
{
    if (rx.IsMatch(word))
    {
        Console.WriteLine($"{word} does match");
    }
    else
    {
        Console.WriteLine($"{word} does not match");
    }
}

该示例执行正则表达式的不区分大小写的匹配。

var rx = new Regex(@"\bdog\b", RegexOptions.Compiled | 
    RegexOptions.IgnoreCase);

通过将 RegexOptions.Compiled 设置为 Regex 的第二个参数来启用不区分大小写的匹配。

C# regex 子模式

子模式是模式中的模式。 子模式使用 () 字符创建。

Program.cs
using System.Text.RegularExpressions;

List<string> words = ["book", "bookshelf", "bookworm",
    "bookcase", "bookish", "bookkeeper", "booklet", "bookmark"];

var rx = new Regex("^book(worm|mark|keeper)?$", RegexOptions.Compiled);

foreach (string word in words)
{
    if (rx.IsMatch(word))
    {
        Console.WriteLine($"{word} does match");
    }
    else
    {
        Console.WriteLine($"{word} does not match");
    }
}

该示例创建一个子模式。

var rx = new Regex("^book(worm|mark|keeper)?$", RegexOptions.Compiled); 

正则表达式使用一个子模式。 它匹配 bookworm、bookmark、bookkeeper 和 book 单词。

C# regex 词频

在下一个示例中,我们统计文件中单词的频率。

$ wget https://raw.githubusercontent.com/janbodnar/data/main/the-king-james-bible.txt

我们使用《英王钦定本圣经》。

Program.cs
using System.Text.RegularExpressions;

var fileName = "/home/janbodnar/Documents/the-king-james-bible.txt";
var text = File.ReadAllText(fileName);

var matches = new Regex("[a-z-A-Z']+").Matches(text);
var words = matches.Select(m => m.Value).ToList();

var res = words
    .GroupBy(m => m)
    .OrderByDescending(g => g.Count())
    .Select(x => new { word = x.Key, Count = x.Count() })
    .Take(10);

foreach (var r in res)
{
    Console.WriteLine($"{r.word}: {r.Count}");
}

在该示例中,我们计算来自《英王钦定本圣经》的单词的频率。

var matches = new Regex("[a-z-A-Z']+").Matches(text);
var words = matches.Select(m => m.Value).ToList();

我们使用 Matches 方法找到所有匹配项。从匹配集合中,我们将所有单词放入一个列表中。

var res = words
    .GroupBy(m => m)
    .OrderByDescending(g => g.Count())
    .Select(x => new { word = x.Key, Count = x.Count() })
    .Take(10);

这些单词按频率降序分组和排序。 我们取前几个单词。

$ dotnet run
the 62103
and 38848
of 34478
to 13400
And 12846
that 12576
in 12331
shall 9760
he 9665
unto 8942

C# regex 电子邮件示例

在下面的示例中,我们创建一个 regex 模式来检查电子邮件地址。

Program.cs
using System.Text.RegularExpressions;

List<string> emails = ["luke@gmail.com", "andy@yahoocom",
    "34234sdfa#2345", "f344@gmail.com"];

var pattern = @"[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,18}";

var rx = new Regex(pattern, RegexOptions.Compiled);

foreach (string email in emails)
{
    if (rx.IsMatch(email))
    {
        Console.WriteLine($"{email} does match");
    }
    else
    {
        Console.WriteLine($"{email} does not match");
    }
}

此示例仅提供一种可能的解决方案。

var pattern = @"[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,18}";

电子邮件分为五个部分。 第一部分是本地部分。 这通常是公司、个人或昵称的名称。 [a-zA-Z0-9._-]+ 列出了所有可能的字符,我们可以在本地部分中使用。 它们可以使用一次或多次。

第二部分由文字 @ 字符组成。 第三部分是域部分。 它通常是电子邮件提供商的域名,如 Yahoo 或 Gmail。 [a-zA-Z0-9-]+ 是一个字符集,提供可以在域名中使用的所有字符。 + 量词使用这些字符中的一个或多个。

第四部分是点字符。 它以转义字符 (\) 开头。 这是因为点字符是一个元字符并具有特殊含义。 通过转义它,我们得到一个文字点。

最后一部分是顶级域:[a-zA-Z.]{2,18}。 顶级域可以有 2 到 18 个字符,例如 sk、net、info、travel、cleaning、travelinsurance。 最大长度可以是 63 个字符,但如今大多数域都短于 18 个字符。 还有一个点字符。 这是因为某些顶级域有两个部分;例如 co.uk。

C# regex 零宽断言 (lookahead and lookbehind assertions)

零宽断言是高级正则表达式功能,允许您仅在某个模式之前或之后跟随着(或不跟着)另一个模式时才匹配该模式。 它们被称为零宽断言是因为它们不消耗输入字符串中的字符。

肯定环视 (Positive lookahead) (?=...) 仅当组之后跟着另一个组时才匹配该组。
否定环视 (Negative lookahead) (?!...) 仅当组之后不跟着另一个组时才匹配该组。
肯定后顾 (Positive lookbehind) (?<=...) 仅当组之前跟着另一个组时才匹配该组。
否定后顾 (Negative lookbehind) (? 仅当组之前不跟着另一个组时才匹配该组。

Program.cs
using System.Text.RegularExpressions;

string text = "catfish catnap dogfish dogcat";

// Positive lookahead: match 'cat' only if followed by 'fish'
var rx1 = new Regex("cat(?=fish)");
foreach (Match m in rx1.Matches(text))
{
    Console.WriteLine($"{m.Value} at {m.Index}");
}

// Negative lookahead: match 'cat' only if NOT followed by 'fish'
var rx2 = new Regex("cat(?!fish)");
foreach (Match m in rx2.Matches(text))
{
    Console.WriteLine($"{m.Value} at {m.Index}");
}

// Positive lookbehind: match 'fish' only if preceded by 'dog'
var rx3 = new Regex("(?<=dog)fish");
foreach (Match m in rx3.Matches(text))
{
    Console.WriteLine($"{m.Value} at {m.Index}");
}

// Negative lookbehind: match 'cat' only if NOT preceded by 'dog'
var rx4 = new Regex("(?<!dog)cat");
foreach (Match m in rx4.Matches(text))
{
    Console.WriteLine($"{m.Value} at {m.Index}");
}

在此示例中,cat(?=fish) 仅当后跟“fish”时才匹配“cat”,例如在“catfish”中,而 cat(?!fish) 仅当后跟“fish”时才匹配“cat”,例如在“catnap”中。 同样,(?<=dog)fish 确保“fish”仅出现在“dog”之后,如“dogfish”中所示,而 (? 仅当以“dog”开头时才匹配“cat”,从而使“catfish”和“catnap”成为有效匹配。

$ dotnet run
cat at 0
cat at 8
cat at 26
fish at 18
cat at 0
cat at 8

来源

Regex 类 - 语言参考

在本文中,我们使用了 C# 中的正则表达式。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程