当前位置: 首页 > news >正文

C#和Java正则表达式开发

C#与Java正则表达式完整开发指南

C#

静态方法和Regex对象两种用法
RegexOptions详解
捕获组和命名组的实战应用
高级替换技巧(MatchEvaluator)

Java

Pattern和Matcher的正确使用
编译标志详解
性能优化技巧(reset重用)
StringBuffer替换高级用法

目录

  1. 正则表达式基础
  2. C#中的正则表达式
  3. Java中的正则表达式
  4. 常用正则表达式模式
  5. 高级技巧与示例

正则表达式基础

元字符详解

元字符说明示例
.匹配任意单个字符(除换行符)a.c 匹配 “abc”, “a5c”
^匹配字符串开始位置^Hello 匹配以"Hello"开头
$匹配字符串结束位置end$ 匹配以"end"结尾
*匹配前面元素0次或多次ab*c 匹配 “ac”, “abc”, “abbc”
+匹配前面元素1次或多次ab+c 匹配 “abc”, “abbc”
?匹配前面元素0次或1次ab?c 匹配 “ac”, “abc”
{n}匹配前面元素恰好n次a{3} 匹配 “aaa”
{n,}匹配前面元素至少n次a{2,} 匹配 “aa”, “aaa”, “aaaa”
{n,m}匹配前面元素n到m次a{2,4} 匹配 “aa”, “aaa”, “aaaa”
[]字符集,匹配其中任一字符[abc] 匹配 “a”, “b”, “c”
[^]否定字符集[^abc] 匹配除a,b,c外的字符
|或运算符cat|dog 匹配 “cat” 或 “dog”
()分组,捕获匹配内容(ab)+ 匹配 “ab”, “abab”
\转义字符\. 匹配实际的点号

字符类

字符类说明等价表达式
\d数字字符[0-9]
\D非数字字符[^0-9]
\w单词字符(字母、数字、下划线)[a-zA-Z0-9_]
\W非单词字符[^a-zA-Z0-9_]
\s空白字符(空格、制表符、换行)[ \t\n\r\f\v]
\S非空白字符[^ \t\n\r\f\v]

贪婪与非贪婪匹配

  • 贪婪匹配(默认): 尽可能多地匹配字符
    • *, +, ?, {n,m}
  • 非贪婪匹配: 尽可能少地匹配字符
    • *?, +?, ??, {n,m}?

示例:

  • 文本: <div>content</div>
  • 贪婪: <.*> 匹配整个字符串
  • 非贪婪: <.*?> 匹配 <div></div>

C#中的正则表达式

引入命名空间

using System.Text.RegularExpressions;

基本使用方法

1. 静态方法 - 简单匹配
// 判断是否匹配
bool isMatch = Regex.IsMatch("Hello123", @"\d+");
Console.WriteLine(isMatch); // True// 查找匹配
Match match = Regex.Match("Hello123World456", @"\d+");
if (match.Success)
{Console.WriteLine(match.Value); // "123"
}// 查找所有匹配
MatchCollection matches = Regex.Matches("Hello123World456", @"\d+");
foreach (Match m in matches)
{Console.WriteLine(m.Value); // "123", "456"
}// 替换
string result = Regex.Replace("Hello123", @"\d+", "XXX");
Console.WriteLine(result); // "HelloXXX"// 分割
string[] parts = Regex.Split("apple,banana;orange", @"[,;]");
// parts = ["apple", "banana", "orange"]
2. Regex对象 - 性能优化
// 创建Regex对象(推荐用于重复使用)
Regex regex = new Regex(@"\d+", RegexOptions.Compiled);// 使用实例方法
bool isMatch = regex.IsMatch("Hello123");
Match match = regex.Match("Hello123");
MatchCollection matches = regex.Matches("Hello123World456");
string result = regex.Replace("Hello123", "XXX");
3. RegexOptions 选项
RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled;Regex regex = new Regex(@"pattern", options);

常用选项:

  • RegexOptions.IgnoreCase - 忽略大小写
  • RegexOptions.Multiline - 多行模式(^和$匹配行首行尾)
  • RegexOptions.Singleline - 单行模式(.匹配包括换行符)
  • RegexOptions.Compiled - 编译正则(提高性能)
  • RegexOptions.IgnorePatternWhitespace - 忽略模式中的空白

C# 实用示例

提取数字
// 提取整数
string text = "订单号:12345,金额:1000元";
Regex regex = new Regex(@"\d+");
MatchCollection matches = regex.Matches(text);
foreach (Match match in matches)
{Console.WriteLine(match.Value); // "12345", "1000"
}// 提取小数
string price = "价格:¥123.45";
Match match = Regex.Match(price, @"\d+\.\d+");
Console.WriteLine(match.Value); // "123.45"// 提取负数和小数
Regex numRegex = new Regex(@"-?\d+\.?\d*");
string text2 = "温度:-15.5度,湿度:80";
foreach (Match m in numRegex.Matches(text2))
{Console.WriteLine(m.Value); // "-15.5", "80"
}
提取和验证邮箱
// 验证邮箱格式
string email = "user@example.com";
bool isValid = Regex.IsMatch(email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");// 提取所有邮箱
string text = "联系方式: john@example.com 或 jane@test.org";
Regex emailRegex = new Regex(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}");
MatchCollection emails = emailRegex.Matches(text);
foreach (Match match in emails)
{Console.WriteLine(match.Value);
}
捕获组的使用
// 提取日期各部分
string text = "日期: 2025-10-01";
Regex dateRegex = new Regex(@"(\d{4})-(\d{2})-(\d{2})");
Match match = dateRegex.Match(text);if (match.Success)
{string year = match.Groups[1].Value;   // "2025"string month = match.Groups[2].Value;  // "10"string day = match.Groups[3].Value;    // "01"Console.WriteLine($"年:{year}, 月:{month}, 日:{day}");
}// 命名捕获组
Regex namedRegex = new Regex(@"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})");
Match namedMatch = namedRegex.Match("2025-10-01");if (namedMatch.Success)
{string year = namedMatch.Groups["year"].Value;string month = namedMatch.Groups["month"].Value;string day = namedMatch.Groups["day"].Value;Console.WriteLine($"年:{year}, 月:{month}, 日:{day}");
}
提取HTML标签内容
string html = "<div class='content'>Hello World</div><p>Test</p>";// 提取标签名和内容
Regex tagRegex = new Regex(@"<(?<tag>\w+)[^>]*>(?<content>.*?)</\k<tag>>");
MatchCollection matches = tagRegex.Matches(html);foreach (Match match in matches)
{string tag = match.Groups["tag"].Value;string content = match.Groups["content"].Value;Console.WriteLine($"标签:{tag}, 内容:{content}");
}
// 输出: 标签:div, 内容:Hello World
//       标签:p, 内容:Test
替换高级用法
// 使用MatchEvaluator进行复杂替换
string text = "价格: 100元, 数量: 5个";
Regex regex = new Regex(@"\d+");string result = regex.Replace(text, match =>
{int num = int.Parse(match.Value);return (num * 2).ToString(); // 所有数字翻倍
});
Console.WriteLine(result); // "价格: 200元, 数量: 10个"// 使用替换组
string phoneText = "电话: 13812345678";
string masked = Regex.Replace(phoneText, @"(\d{3})\d{4}(\d{4})", "$1****$2");
Console.WriteLine(masked); // "电话: 138****5678"

Java中的正则表达式

引入类库

import java.util.regex.Pattern;
import java.util.regex.Matcher;

基本使用方法

1. 静态方法 - 简单匹配
// 判断是否匹配
boolean isMatch = Pattern.matches("\\d+", "12345");
System.out.println(isMatch); // true// 注意: Java字符串中\需要转义为\\
String regex = "\\d+";  // 等同于C#的 @"\d+"
2. Pattern和Matcher对象
// 创建Pattern对象
Pattern pattern = Pattern.compile("\\d+");// 创建Matcher对象
Matcher matcher = pattern.matcher("Hello123World456");// 查找匹配
if (matcher.find()) {System.out.println(matcher.group()); // "123"System.out.println("开始位置: " + matcher.start()); // 5System.out.println("结束位置: " + matcher.end());   // 8
}// 查找所有匹配
while (matcher.find()) {System.out.println(matcher.group());
}// 重置matcher以重新匹配
matcher.reset();// 替换
String result = matcher.replaceAll("XXX");
System.out.println(result); // "HelloXXXWorldXXX"// 替换第一个匹配
String resultFirst = matcher.replaceFirst("XXX");
System.out.println(resultFirst); // "HelloXXXWorld456"
3. Pattern编译标志
// 使用标志
Pattern pattern = Pattern.compile("pattern", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);// 或使用内嵌标志
Pattern pattern2 = Pattern.compile("(?i)(?m)pattern");

常用标志:

  • Pattern.CASE_INSENSITIVE - 忽略大小写
  • Pattern.MULTILINE - 多行模式
  • Pattern.DOTALL - 点号匹配所有字符(包括换行)
  • Pattern.UNICODE_CASE - Unicode大小写匹配
  • Pattern.COMMENTS - 允许注释和空白

Java 实用示例

提取数字
// 提取所有整数
String text = "订单号:12345,金额:1000元";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);while (matcher.find()) {System.out.println(matcher.group()); // "12345", "1000"
}// 提取小数
String price = "价格:¥123.45";
Pattern decimalPattern = Pattern.compile("\\d+\\.\\d+");
Matcher decimalMatcher = decimalPattern.matcher(price);if (decimalMatcher.find()) {System.out.println(decimalMatcher.group()); // "123.45"
}// 提取负数和小数
Pattern numPattern = Pattern.compile("-?\\d+\\.?\\d*");
String text2 = "温度:-15.5度,湿度:80";
Matcher numMatcher = numPattern.matcher(text2);while (numMatcher.find()) {System.out.println(numMatcher.group()); // "-15.5", "80"
}
提取和验证邮箱
// 验证邮箱格式
String email = "user@example.com";
String emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
boolean isValid = Pattern.matches(emailRegex, email);
System.out.println("邮箱有效: " + isValid);// 提取所有邮箱
String text = "联系方式: john@example.com 或 jane@test.org";
Pattern emailPattern = Pattern.compile("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
Matcher emailMatcher = emailPattern.matcher(text);while (emailMatcher.find()) {System.out.println(emailMatcher.group());
}
捕获组的使用
// 提取日期各部分
String text = "日期: 2025-10-01";
Pattern datePattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher dateMatcher = datePattern.matcher(text);if (dateMatcher.find()) {String fullMatch = dateMatcher.group(0); // "2025-10-01"String year = dateMatcher.group(1);      // "2025"String month = dateMatcher.group(2);     // "10"String day = dateMatcher.group(3);       // "01"System.out.println(String.format("年:%s, 月:%s, 日:%s", year, month, day));
}// 命名捕获组
Pattern namedPattern = Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})");
Matcher namedMatcher = namedPattern.matcher("2025-10-01");if (namedMatcher.find()) {String year = namedMatcher.group("year");String month = namedMatcher.group("month");String day = namedMatcher.group("day");System.out.println(String.format("年:%s, 月:%s, 日:%s", year, month, day));
}
提取HTML标签内容
String html = "<div class='content'>Hello World</div><p>Test</p>";// 提取标签名和内容
Pattern tagPattern = Pattern.compile("<(?<tag>\\w+)[^>]*>(?<content>.*?)</\\k<tag>>");
Matcher tagMatcher = tagPattern.matcher(html);while (tagMatcher.find()) {String tag = tagMatcher.group("tag");String content = tagMatcher.group("content");System.out.println("标签:" + tag + ", 内容:" + content);
}
// 输出: 标签:div, 内容:Hello World
//       标签:p, 内容:Test
分割字符串
// 使用Pattern.split()
String text = "apple,banana;orange:grape";
Pattern splitPattern = Pattern.compile("[,;:]");
String[] parts = splitPattern.split(text);for (String part : parts) {System.out.println(part);
}
// 输出: apple, banana, orange, grape// 使用String.split() (内部使用Pattern)
String[] parts2 = text.split("[,;:]");
替换高级用法
// 简单替换
String text = "价格: 100元, 数量: 5个";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);String result = matcher.replaceAll("XXX");
System.out.println(result); // "价格: XXX元, 数量: XXX个"// 使用Matcher.appendReplacement进行复杂替换
StringBuffer sb = new StringBuffer();
matcher.reset(); // 重置matcherwhile (matcher.find()) {int num = Integer.parseInt(matcher.group());matcher.appendReplacement(sb, String.valueOf(num * 2));
}
matcher.appendTail(sb);
System.out.println(sb.toString()); // "价格: 200元, 数量: 10个"// 使用替换组
String phoneText = "电话: 13812345678";
String masked = phoneText.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
System.out.println(masked); // "电话: 138****5678"
边界匹配
// 单词边界
String text = "cat catch category";
Pattern wordPattern = Pattern.compile("\\bcat\\b");
Matcher wordMatcher = wordPattern.matcher(text);while (wordMatcher.find()) {System.out.println(wordMatcher.group()); // 只匹配 "cat"
}// 行首行尾(需要MULTILINE模式)
String multiLineText = "Line1\nLine2\nLine3";
Pattern linePattern = Pattern.compile("^Line", Pattern.MULTILINE);
Matcher lineMatcher = linePattern.matcher(multiLineText);int count = 0;
while (lineMatcher.find()) {count++;
}
System.out.println("匹配行数: " + count); // 3

常用正则表达式模式

数字匹配

整数:              ^\d+$ 或 ^[0-9]+$
正整数:            ^[1-9]\d*$
负整数:            ^-[1-9]\d*$
整数(包括正负):    ^-?\d+$小数:              ^\d+\.\d+$
正小数:            ^[1-9]\d*\.\d+|0\.\d*[1-9]\d*$
负小数:            ^-([1-9]\d*\.\d+|0\.\d*[1-9]\d*)$
浮点数:            ^-?\d+\.?\d*$科学计数法:        ^-?\d+\.?\d*[eE][+-]?\d+$

示例代码 (C#):

// 验证整数
bool isInteger = Regex.IsMatch("12345", @"^\d+$");// 验证小数(保留2位)
bool isDecimal = Regex.IsMatch("123.45", @"^\d+\.\d{2}$");// 提取所有数字(包括小数)
string text = "价格:¥123.45,数量:10";
MatchCollection numbers = Regex.Matches(text, @"-?\d+\.?\d*");

示例代码 (Java):

// 验证整数
boolean isInteger = Pattern.matches("^\\d+$", "12345");// 验证小数(保留2位)
boolean isDecimal = Pattern.matches("^\\d+\\.\\d{2}$", "123.45");// 提取所有数字(包括小数)
String text = "价格:¥123.45,数量:10";
Pattern pattern = Pattern.compile("-?\\d+\\.?\\d*");
Matcher matcher = pattern.matcher(text);

字符串匹配

英文字母:          ^[a-zA-Z]+$
小写字母:          ^[a-z]+$
大写字母:          ^[A-Z]+$
字母和数字:        ^[a-zA-Z0-9]+$
字母数字下划线:    ^\w+$中文字符:          ^[\u4e00-\u9fa5]+$
中英文数字:        ^[\u4e00-\u9fa5a-zA-Z0-9]+$不包含特殊字符:    ^[a-zA-Z0-9\u4e00-\u9fa5]+$

示例代码 (C#):

// 验证只包含字母
bool isAlpha = Regex.IsMatch("HelloWorld", @"^[a-zA-Z]+$");// 验证中文
bool isChinese = Regex.IsMatch("你好世界", @"^[\u4e00-\u9fa5]+$");// 提取所有中文
string text = "Hello你好World世界";
MatchCollection chinese = Regex.Matches(text, @"[\u4e00-\u9fa5]+");

示例代码 (Java):

// 验证只包含字母
boolean isAlpha = Pattern.matches("^[a-zA-Z]+$", "HelloWorld");// 验证中文
boolean isChinese = Pattern.matches("^[\\u4e00-\\u9fa5]+$", "你好世界");// 提取所有中文
String text = "Hello你好World世界";
Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]+");
Matcher matcher = pattern.matcher(text);

日期和时间

日期 YYYY-MM-DD:   ^\d{4}-\d{2}-\d{2}$
日期 YYYY/MM/DD:   ^\d{4}/\d{2}/\d{2}$
日期 DD-MM-YYYY:   ^\d{2}-\d{2}-\d{4}$时间 HH:MM:        ^([01]\d|2[0-3]):[0-5]\d$
时间 HH:MM:SS:     ^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$日期时间:          ^\d{4}-\d{2}-\d{2}\s+([01]\d|2[0-3]):[0-5]\d:[0-5]\d$
ISO 8601:          ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$

示例代码 (C#):

// 验证日期格式
string datePattern = @"^\d{4}-\d{2}-\d{2}$";
bool isValidDate = Regex.IsMatch("2025-10-01", datePattern);// 提取日期各部分
string text = "会议时间: 2025-10-01 14:30:00";
Match match = Regex.Match(text, @"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})\s+(?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})");if (match.Success)
{Console.WriteLine($"年: {match.Groups["year"].Value}");Console.WriteLine($"月: {match.Groups["month"].Value}");Console.WriteLine($"日: {match.Groups["day"].Value}");Console.WriteLine($"时: {match.Groups["hour"].Value}");Console.WriteLine($"分: {match.Groups["minute"].Value}");Console.WriteLine($"秒: {match.Groups["second"].Value}");
}

网络相关

IP地址:            ^(\d{1,3}\.){3}\d{1,3}$
精确IP(0-255):     ^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$URL:               ^https?://[^\s/$.?#].[^\s]*$
域名:              ^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$邮箱:              ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

示例代码 (C#):

// 验证邮箱
string emailPattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
bool isValidEmail = Regex.IsMatch("user@example.com", emailPattern);// 验证URL
string urlPattern = @"^https?://[^\s/$.?#].[^\s]*$";
bool isValidUrl = Regex.IsMatch("https://www.example.com", urlPattern);// 提取URL
string text = "访问 https://example.com 或 http://test.org";
MatchCollection urls = Regex.Matches(text, @"https?://[^\s]+");
foreach (Match match in urls)
{Console.WriteLine(match.Value);
}

电话号码

中国手机号:        ^1[3-9]\d{9}$
中国固话:          ^0\d{2,3}-?\d{7,8}$美国电话:          ^\d{3}-\d{3}-\d{4}$
国际格式:          ^\+\d{1,3}\s?\d{1,14}$

示例代码 (Java):

// 验证中国手机号
String phonePattern = "^1[3-9]\\d{9}$";
boolean isValidPhone = Pattern.matches(phonePattern, "13812345678");// 提取电话号码
String text = "联系电话: 138-1234-5678 或 010-12345678";
Pattern pattern = Pattern.compile("\\d{3}-?\\d{4}-?\\d{4}|0\\d{2,3}-?\\d{7,8}");
Matcher matcher = pattern.matcher(text);while (matcher.find()) {System.out.println(matcher.group());
}

身份证号

中国身份证15位:    ^\d{15}$
中国身份证18位:    ^\d{17}[\dXx]$
通用:              ^\d{15}|\d{17}[\dXx]$

密码强度

至少8位字母数字:   ^[a-zA-Z0-9]{8,}$
必须包含大小写字母和数字:  ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$
必须包含大小写字母数字和特殊字符:  ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$

示例代码 (C#):

// 验证强密码(至少8位,包含大小写字母和数字)
string passwordPattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$";
bool isStrongPassword = Regex.IsMatch("MyPass123", passwordPattern);// 检查密码强度
string CheckPasswordStrength(string password)
{if (Regex.IsMatch(password, @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{12,}$"))return "很强";if (Regex.IsMatch(password, @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$"))return "强";if (Regex.IsMatch(password, @"^[a-zA-Z0-9]{6,}$"))return "中";return "弱";
}

位置和边界

行首:              ^pattern
行尾:              pattern$
单词边界:          \bword\b
非单词边界:        \Bword\B字符串开始:        \Apattern
字符串结束:        pattern\Z环视:正向前瞻:        pattern(?=check)负向前瞻:        pattern(?!check)正向后顾:        (?<=check)pattern负向后顾:        (?<!check)pattern

示例代码 (C#):

// 匹配单词边界
string text = "cat catch category";
MatchCollection matches = Regex.Matches(text, @"\bcat\b");
// 只匹配独立的 "cat",不匹配 "catch" 和 "category"// 正向前瞻: 匹配后面跟着 "bar" 的 "foo"
string text2 = "foobar foobaz";
MatchCollection matches2 = Regex.Matches(text2, @"foo(?=bar)");
// 只匹配 "foobar" 中的 "foo"// 负向前瞻: 匹配后面不跟 "bar" 的 "foo"
MatchCollection matches3 = Regex.Matches(text2, @"foo(?!bar)");
// 只匹配 "foobaz" 中的 "foo"// 正向后顾: 匹配前面是 "USD" 的数字
string price = "USD100 EUR200 USD150";
MatchCollection matches4 = Regex.Matches(price, @"(?<=USD)\d+");
// 匹配 "100" 和 "150"

示例代码 (Java):

// 匹配行首的特定单词(多行模式)
String text = "Hello World\nHello Java\nGoodbye World";
Pattern pattern = Pattern.compile("^Hello", Pattern.MULTILINE);
Matcher matcher = pattern.matcher(text);while (matcher.find()) {System.out.println("找到行首的Hello,位置: " + matcher.start());
}// 环视示例
String text2 = "100美元 200欧元 300美元";
Pattern pattern2 = Pattern.compile("(?<=\\d{3})美元");
Matcher matcher2 = pattern2.matcher(text2);
// 匹配前面是三位数字的"美元"

高级技巧与示例

1. 命名捕获组和反向引用

C#:

// 查找重复的单词
string text = "the the cat sat sat on the mat";
Regex regex = new Regex(@"\b(?<word>\w+)\s+\k<word>\b");
MatchCollection matches = regex.Matches(text);foreach (Match match in matches)
{Console.WriteLine($"重复单词: {match.Groups["word"].Value}");
}
// 输出: the, sat// HTML标签匹配(确保开闭标签一致)
string html = "<div>content</div><span>text</span>";
Regex tagRegex = new Regex(@"<(?<tag>\w+)>.*?</\k<tag>>");

Java:

// 查找重复的单词
String text = "the the cat sat sat on the mat";
Pattern pattern = Pattern.compile("\\b(?<word>\\w+)\\s+\\k<word>\\b");
Matcher matcher = pattern.matcher(text);while (matcher.find()) {System.out.println("重复单词: " + matcher.group("word"));
}

2. 贪婪与非贪婪匹配实战

C#:

string html = "<div>First</div><div>Second</div>";// 贪婪匹配
Match greedyMatch = Regex.Match(html, @"<div>.*</div>");
Console.WriteLine(greedyMatch.Value);
// 输出: <div>First</div><div>Second</div>// 非贪婪匹配
MatchCollection lazyMatches = Regex.Matches(html, @"<div>.*?</div>");
foreach (Match match in lazyMatches)
{Console.WriteLine(match.Value);
}
// 输出: <div>First</div>
//       <div>Second</div>

3. 性能优化技巧

C#:

// 1. 使用编译选项提高重复使用的性能
Regex compiled = new Regex(@"\d+", RegexOptions.Compiled);// 2. 重用Regex对象
Regex reusable = new Regex(@"pattern");
for (int i = 0; i < 1000; i++)
{reusable.IsMatch(texts[i]); // 比每次new Regex快得多
}// 3. 使用静态缓存(Regex内部自动缓存最近15个)
bool match = Regex.IsMatch(text, @"pattern"); // 会被缓存// 4. 限制回溯(使用原子组或占有量词)
// 不好: ^.*(\d+)$ 可能导致大量回溯
// 好:   ^.*?(\d+)$ 或 ^[^\d]*(\d+)$

Java:

// 1. 重用Pattern对象
Pattern pattern = Pattern.compile("\\d+");
for (int i = 0; i < 1000; i++) {Matcher matcher = pattern.matcher(texts[i]);matcher.find();
}// 2. 使用Matcher.reset()重用Matcher对象
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("");for (String text : texts) {matcher.reset(text);while (matcher.find()) {// 处理匹配}
}// 3. 避免复杂的回溯
// 使用原子组: (?>...)
// 使用占有量词: *+, ++, ?+

4. 复杂数据提取示例

C#完整示例 - 日志解析:

string logText = @"
[2025-10-01 14:30:15] INFO: User login successful - UserID: 12345
[2025-10-01 14:35:22] ERROR: Database connection failed - Code: 500
[2025-10-01 14:40:10] WARN: Memory usage high - 85%
";string logPattern = @"\[(?<date>\d{4}-\d{2}-\d{2})\s+(?<time>\d{2}:\d{2}:\d{2})\]\s+(?<level>\w+):\s+(?<message>.+)";
Regex logRegex = new Regex(logPattern);MatchCollection logMatches = logRegex.Matches(logText);foreach (Match match in logMatches)
{Console.WriteLine($"日期: {match.Groups["date"].Value}");Console.WriteLine($"时间: {match.Groups["time"].Value}");Console.WriteLine($"级别: {match.Groups["level"].Value}");Console.WriteLine($"消息: {match.Groups["message"].Value}");Console.WriteLine("---");
}

Java完整示例 - JSON简单解析:

String jsonText = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";// 提取键值对
Pattern kvPattern = Pattern.compile("\"(?<key>\\w+)\":\"?(?<value>[^,}\"]+)\"?");
Matcher kvMatcher = kvPattern.matcher(jsonText);Map<String, String> jsonMap = new HashMap<>();
while (kvMatcher.find()) {String key = kvMatcher.group("key");String value = kvMatcher.group("value");jsonMap.put(key, value);System.out.println(key + " = " + value);
}

5. 实用工具方法

C# 工具类:

public static class RegexHelper
{// 验证邮箱public static bool IsValidEmail(string email){return Regex.IsMatch(email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");}// 验证手机号public static bool IsValidPhone(string phone){return Regex.IsMatch(phone, @"^1[3-9]\d{9}$");}// 提取所有数字public static List<string> ExtractNumbers(string text){MatchCollection matches = Regex.Matches(text, @"-?\d+\.?\d*");return matches.Cast<Match>().Select(m => m.Value).ToList();}// 移除HTML标签public static string RemoveHtmlTags(string html){return Regex.Replace(html, @"<[^>]+>", "");}// 驼峰转下划线public static string CamelToSnake(string camelCase){return Regex.Replace(camelCase, @"([a-z])([A-Z])", "$1_$2").ToLower();}
}

Java 工具类:

public class RegexHelper {// 验证邮箱public static boolean isValidEmail(String email) {return Pattern.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email);}// 验证手机号public static boolean isValidPhone(String phone) {return Pattern.matches("^1[3-9]\\d{9}$", phone);}// 提取所有数字public static List<String> extractNumbers(String text) {List<String> numbers = new ArrayList<>();Pattern pattern = Pattern.compile("-?\\d+\\.?\\d*");Matcher matcher = pattern.matcher(text);while (matcher.find()) {numbers.add(matcher.group());}return numbers;}// 移除HTML标签public static String removeHtmlTags(String html) {return html.replaceAll("<[^>]+>", "");}// 驼峰转下划线public static String camelToSnake(String camelCase) {return camelCase.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();}
}

常见陷阱与注意事项

1. 转义字符差异

C#: 使用 @ 字符串前缀避免双重转义

string pattern = @"\d+";  // 推荐
string pattern2 = "\\d+"; // 也可以,但不推荐

Java: 必须双重转义

String pattern = "\\d+";  // 必须
String pattern2 = "\d+";  // 错误!

2. 性能陷阱

// 灾难性回溯示例(避免!)
^(a+)+$
^(a*)*$
^(a|a)*$// 对输入 "aaaaaaaaaaaaaaaaaab" 会导致指数级回溯// 改进方案
^a+$
^a*$

3. 点号不匹配换行符

// 默认情况下 . 不匹配换行符
// 使用 Singleline (Java中是DOTALL) 选项
Regex regex = new Regex(@"<div>.*?</div>", RegexOptions.Singleline);
Pattern pattern = Pattern.compile("<div>.*?</div>", Pattern.DOTALL);

4. Unicode支持

// C# 默认支持Unicode
Regex regex = new Regex(@"[\u4e00-\u9fa5]+"); // 中文字符
// Java 需要启用UNICODE_CASE等标志
Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]+", Pattern.UNICODE_CASE);

总结与最佳实践

1. 基本原则

  • 优先使用简单明确的模式
  • 避免过度使用正则表达式(某些情况字符串方法更合适)
  • 充分测试边界情况

2. 性能考虑

  • 重用编译后的Regex/Pattern对象
  • 避免灾难性回溯
  • 使用非贪婪匹配时考虑性能影响

3. 可维护性

  • 使用注释模式说明复杂正则表达式
  • 使用命名捕获组提高可读性
  • 将常用正则提取为常量

4. 安全性

  • 验证用户输入时使用严格的正则
  • 注意ReDoS攻击(正则拒绝服务)
  • 不要使用正则处理HTML/XML(使用专门的解析器)

5. 调试工具

  • Regex101.com - 在线测试和调试
  • RegExr.com - 可视化正则表达式
  • IDE内置的正则测试工具

参考资源

  • C# 官方文档: Microsoft Docs - Regular Expressions
  • Java 官方文档: Oracle Docs - Pattern Class
  • 在线测试工具: Regex101
  • 正则表达式可视化: RegExper
http://www.dtcms.com/a/430637.html

相关文章:

  • 从零开始:MCP数据库助手(一)- 基础搭建
  • ORB_SLAM2原理及代码解析:SetPose() 函数
  • 蚌埠市建设学校网站网站排名权重怎么做
  • Android android.util.LruCache源码阅读
  • 安卓基础组件020-页面跳转传递数据001
  • Postman 学习笔记 IV:Workflow、Newman 与 Mock Server 实战技巧
  • 安卓基础组件016--第三方Toasty组件
  • ESNP LAB 笔记:配置静态BFD检测MPLS LDP LSP
  • Day30 | Java集合框架之Collections工具类
  • 【STM32项目开源】基于STM32的智能养殖场环境监测系统
  • 【Java并发】揭秘Lock体系 -- condition等待通知机制
  • 计算机网络-网络边缘网络核心
  • 安卓13_ROM修改定制化-----修改固件 去除主题防止恢复 破解主题等操作解析
  • 怎么做网站301重定向可口可乐公司的企业网站建设
  • NS4168输出音频通过ESP32C3测试
  • 24.使用 HTML 和 CSS 实现无限旋转正方形动画效果
  • 音频降噪技术:从原理到工具的完整指南(scipy librosa noisereduce soundfile pedalboard)
  • 网站建设构成技术要求wordpress书籍推荐
  • CoCoSim(2020): 连接Simulink与Lustre生态的模型检测框架
  • 第2篇|风机设计的基本原则:从“会弯的高楼”到“会自救的系统”
  • SpringSecurity详解
  • [linux仓库]深入解析Linux动态链接与动态库加载:理解背后的原理与技巧
  • 异步日志系统
  • 自监督学习在医疗AI中的技术实现路径分析(中)
  • QoS之拥塞管理两种配置方法
  • tp框架做网站的优点郑州品牌策划设计公司
  • 浅析 AC 自动机
  • Docker常见问题与解决
  • Rokid手势识别技术深度剖析
  • java web搭建商城购物车