Unicode 编码范围
中文在 Unicode 编码中占据着特定的范围,正则表达式通过匹配这些范围内的字符来实现对中文的识别。

最常用的 Unicode 范围包括:
- 基本汉字:
\u4e00-\u9fff这是最核心、最常用的范围,包含了绝大多数日常使用的简体和繁体汉字。
- 扩展 A 区:
\u3400-\u4dbf包含了一些不常用的汉字,例如一些生僻的古字。
- 扩展 B-F 区:
\u20000-\u2a6df,\u2a700-\u2b73f,\u2b740-\u2b81f,\u2b820-\u2ceaf,\u2ceb0-\u2ebef包含了更多的生僻、罕见汉字。
(图片来源网络,侵删) - 兼容汉字:
\uf900-\ufaff主要用于兼容旧标准,通常不推荐在匹配中包含。
注意:\u4e00 - \u9fff 已经能满足 99% 的场景,如果你的文本中包含罕见的生僻字,才需要考虑扩展区。
匹配纯中文字符串
如果你的目标是整个字符串必须且只能包含中文,可以使用 ^ (字符串开始) 和 (字符串结束) 进行锚定。
正则表达式:

^[\u4e00-\u9fff]+$
^: 匹配字符串的开头。[\u4e00-\u9fff]: 匹配一个在基本汉字范围内的任意字符。- 匹配前面的元素一次或多次。
- 匹配字符串的结尾。
Java 代码示例:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatchChineseOnly {
public static void main(String[] args) {
// 要测试的字符串
String str1 = "你好世界"; // 纯中文
String str2 = "Hello 世界"; // 包含英文
String str3 = "你好,世界!"; // 包含标点符号
String str4 = ""; // 空字符串
// 编译正则表达式
// Pattern.CASE_INSENSITIVE 在这里没有影响,但是一个好习惯
Pattern pattern = Pattern.compile("^[\u4e00-\u9fff]+$");
System.out.println("--- 测试匹配纯中文字符串 ---");
testString(pattern, str1); // 应该匹配
testString(pattern, str2); // 不匹配
testString(pattern, str3); // 不匹配
testString(pattern, str4); // 不匹配
}
public static void testString(Pattern pattern, String str) {
Matcher matcher = pattern.matcher(str);
if (matcher.matches()) {
System.out.println("\"" + str + "\" 是一个纯中文字符串。");
} else {
System.out.println("\"" + str + "\" 不是一个纯中文字符串。");
}
}
}
输出:
--- 测试匹配纯中文字符串 ---
"你好世界" 是一个纯中文字符串。
"Hello 世界" 不是一个纯中文字符串。
"你好,世界!" 不是一个纯中文字符串。
"" 不是一个纯中文字符串。
匹配字符串中的中文字符(更常用)
在大多数情况下,我们只想从一个包含中文、英文、数字、符号的混合字符串中提取出所有的中文。
正则表达式:
[\u4e00-\u9fff]+
这个表达式去掉了 ^ 和 ,所以它会匹配字符串中任意位置的、一个或多个连续的中文。
Java 代码示例:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class FindChineseInString {
public static void main(String[] args) {
String mixedString = "我的邮箱是 test@example.com,联系电话是 138-1234-5678。";
// 编译正则表达式
Pattern pattern = Pattern.compile("[\u4e00-\u9fff]+");
// 创建 Matcher 对象
Matcher matcher = pattern.matcher(mixedString);
System.out.println("--- 从混合字符串中提取中文 ---");
System.out.println("原始字符串: " + mixedString);
System.out.print("提取出的中文: ");
// 使用 find() 和 group() 来查找和获取所有匹配项
while (matcher.find()) {
// group() 返回最近一次匹配的子序列
System.out.print(matcher.group() + " ");
}
System.out.println(); // 换行
}
}
输出:
--- 从混合字符串中提取中文 ---
原始字符串: 我的邮箱是 test@example.com,联系电话是 138-1234-5678。
提取出的中文: 我的 邮箱 是 联系电话 是
包含标点符号和扩展汉字
我们不仅想匹配汉字,还想匹配中文的标点符号(如 )等,这需要将标点符号的 Unicode 范围也加入到字符集中。
正则表达式:
[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]+
\u3000-\u303f: 主要匹配中文全角标点符号(如 )。\uff00-\uffef: 主要匹配半角及全角形式的标点符号(如 )。
Java 代码示例:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatchChineseWithPunctuation {
public static void main(String[] args) {
String complexString = "你好,世界!This is a test. (测试123)";
// 编译正则表达式,增加了标点符号的范围
Pattern pattern = Pattern.compile("[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]+");
Matcher matcher = pattern.matcher(complexString);
System.out.println("--- 匹配中文和标点 ---");
System.out.println("原始字符串: " + complexString);
System.out.print("匹配结果: ");
while (matcher.find()) {
System.out.print("[" + matcher.group() + "] ");
}
System.out.println();
}
}
输出:
--- 匹配中文和标点 ---
原始字符串: 你好,世界!This is a test. (测试123)
匹配结果: [你好,世界!] [(测试)]
注意:上面的标点符号范围可能不够全面,因为中文标点符号非常丰富,你可以根据需要添加更多的 Unicode 范围,一个更全面(但可能也包含一些非标点符号)的常见范围是
[\u4e00-\u9\uffef]。
更全面的匹配(包含扩展汉字)
如果需要匹配包含罕见生僻字的文本,可以将扩展区也加入。
正则表达式:
[\u4e00-\u9fff\u3400-\u4dbf\U00020000-\U0002a6df\U0002a700-\U0002b73f\U0002b740-\U0002b81f\U0002b820-\U0002ceaf\U0002ceb0-\U0002ebef]+
注意:在 Java 中,对于 \u 之外的辅助平面(Supplementary Planes)的字符(如 \U00020000),需要使用 \U 并用8位十六进制表示。
Java 代码示例:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatchAllChinese {
public static void main(String[] args) {
// "𠮷" 是一个生僻字,位于扩展B区 (U+20BB7)
String rareCharString = "𠮷𠮷 你好";
// 编译包含扩展区的正则表达式
// 注意:\U 必须使用大写,并且是8位十六进制
Pattern pattern = Pattern.compile("[\\u4e00-\\u9fff\\u3400-\\u4dbf\\U00020000-\\U0002a6df\\U0002a700-\\U0002b73f\\U0002b740-\\U0002b81f\\U0002b820-\\U0002ceaf\\U0002ceb0-\\U0002ebef]+");
Matcher matcher = pattern.matcher(rareCharString);
System.out.println("--- 匹配所有汉字(含扩展区)---");
System.out.println("原始字符串: " + rareCharString);
System.out.print("匹配结果: ");
while (matcher.find()) {
System.out.print("[" + matcher.group() + "] ");
}
System.out.println();
}
}
输出:
--- 匹配所有汉字(含扩展区)---
原始字符串: 𠮷𠮷 你好
匹配结果: [𠮷𠮷 你好]
注意:处理这些辅助平面的字符时,Java 的
String.length()和charAt()等方法可能会返回意想不到的结果( 的length()是2),因为它们在内部被表示为两个 "代理项对"(surrogate pairs),但在正则表达式匹配中,matcher.group()会正确地返回完整的字符。
总结与最佳实践
| 场景 | 正则表达式 | 说明 |
|---|---|---|
| 匹配纯中文 | ^[\u4e00-\u9fff]+$ |
字符串从头到尾只能是中文。 |
| 提取中文 | [\u4e00-\u9fff]+ |
最常用,从混合文本中找出所有连续的中文。 |
| 中文+标点 | [\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]+ |
匹配中文和常见的中文标点符号。 |
| 所有汉字 | [\u4e00-\u9fff\u3400-\u4dbf\U00020000-\U0002ebef]+ |
包含基本汉字和所有扩展区的罕见汉字。 |
建议:
- 从简单开始:优先使用
[\u4e00-\u9fff]+,它能解决绝大多数问题。 - 明确需求:你的任务是验证整个字符串(用
^...$)还是提取部分内容(不用锚定)? - 考虑标点:如果需要匹配句子或段落,请务必将标点符号的范围加入。
- 性能:对于非常大的文本,复杂的正则表达式(包含很多范围)可能会影响性能,但在一般情况下,这些正则表达式已经足够高效。
