前两天遇到一个需求,大概是这样:
有"放射性废物分类", "放射性物质", "放射性", "放射", "性" 这样一组词语,要在 这样一段话中匹配 ''关于发布《放射性废物分类》的公告,放射性物质是有害物质,放射元素会影响人的医生",要求如果长的包含短的只匹配长的,比如放射性包含放射和性,在放射性物质中只匹配放射性,匹配到的要前后加<em></em>
实现这样的功能就想到了正则表达式,下面先了解简单的正则语法
1.正则表达式介绍
正则表达式(Regular Expression),通常简称为"正则"或"Regex",是⼀种⽤于描述字符串模式 的表达式。它是由字符和运算符组成的⽂本模式,⽤于匹配、查找或替换⽂本中的字符序列。
主要功能 :
匹配⽂本模式; 查找和替换 ;数据提取 ; 表单验证 ; ⽂本处理⼯具。
2.正则表达式语法
正则表达式(正则)的语法由⼀系列字符和操作符组成,⽤于定义字符串的模式。以下是⼀些常⻅ 的正则表达式语法元素:
2.1字⾯字符
普通字符: ⼤多数字符表示它们⾃身。例如,字⺟和数字⼤多直接匹配⾃身。
2.2元字符
-
.(点):
匹配除换⾏符之外的任意字符。 a.b // 匹配 "aab"、"axb"、"a@b" 等
-
^: 匹配字符串的开头。
^abc // 匹配以 "abc" 开头的字符串
-
$: 匹配字符串的结尾。
xyz$ // 匹配以 "xyz" 结尾的字符串
-
\d \D 匹配⼀个数字或⾮数字
-
\n 匹配换⾏符
-
\s \S 匹配空⽩字符 或 ⾮空⽩字符
-
\w \W 匹配任何单词 或 ⾮单词 [A-Za-z0-9_]
2.3 字符类
[...]: 匹配⽅括号内的任何字符
[aeiou] // 匹配任何⼀个元⾳字⺟
^ 表示取反,匹配不在⽅括号内的任何字符。
[^0-9] // 匹配任何⾮数字字符
2.4量词
-
*: 匹配零次或多次前⾯的元素。
a* // 匹配 "a"、"aa"、"aaa" 等
-
+: 匹配⼀次或多次前⾯的元素。
b+ // 匹配 "b"、"bb"、"bbb" 等
-
?: 匹配零次或⼀次前⾯的元素。
c? // 匹配 "c" 或空字符串
-
{n}: 匹配恰好 n 次前⾯的元素。
d{3} // 匹配 "ddd"
-
{n,}: 匹配⾄少 n 次前⾯的元素。
e{2,} // 匹配 "ee"、"eee"、"eeee" 等
-
{n,m}: 匹配⾄少 n 次且不超过 m 次前⾯的元素。
f{2,4} // 匹配 "ff"、"fff"、"ffff"
这些元素只是正则表达式语法的⼀部分,正则表达式还有许多⾼级特性和选项,具体取决于⽀持正 则表达式的⼯具或语⾔。学习正则表达式通常需要不断练习和实践,逐渐掌握其强⼤的⽂本匹配和 处理能⼒
3.正则表达式⾼级特性
3.1 转义字符
\: 转义字符,⽤于匹配元字符本身。
\. // 匹配句点字符 "."
\? // 匹配?
\+ // 匹配+
\* // 匹配*
3.2分组和捕获
(...): 创建⼀个分组,可以对其应⽤量词。
(abc)+ // 匹配 "abc"、"abcabc" 等 group(1) 可以获取
(?:...): ⾮捕获分组,不捕获匹配的内容。
(?:ab)+ // 匹配 "ab"、"abab" 等,group(1) 获取不到
3.3 零宽断⾔
(?=...): 正向肯定预查,匹配在某些内容之前的位置。
a(?=b) // 匹配 "a",但仅当其后⾯跟着"b"
(?!...): 正向否定预查,匹配不在某些内容之前的位置。
x(?!y) // 匹配 "x",但仅当其后⾯不跟着 "y"
(?<=...): 反向肯定预查,匹配在某些内容之后的位置。
(?<=a)b // 匹配 "b",但仅当其前⾯是 "a"
(?<!...):反向否定预查,匹配不在某些内容之后的位置
(?<!x)y //匹配y,但前边不是x
5.使⽤正则提取指定的内容
提取数字:
public void testNum() {
String text = "这⾥有⼀些数字:12, 34, 56, 78";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(matcher.group());
}
}
提取XML属性
public void testXMLAttr() {
String text = "<a text=\"value\">Example</a>";
Pattern pattern = Pattern.compile("a\\s*=\\s*\"[^\"]+\"");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(matcher.group());
}
}
结果:
text="value"
6.实现问题功能
java
public class KeywordHighlighter {
public static void main(String[] args) {
// 给定的一段话
String text = "关于发布《放射性废物分类》的公告,放射性物质是有害物质,放射元素会影响人的医生";
// 关键词列表,按长度降序排列
String[] keywords = {"放射性废物分类", "放射性物质", "放射性", "放射", "性"};
// 调用方法进行匹配和高亮
String highlightedText = replaceKeywords(text, keywords);
// 打印结果
System.out.println(highlightedText);
}
public static String replaceKeywords(String text, String[] keywords) {
// 按长度降序排序关键词
Arrays.sort(keywords, (a, b) -> b.length() - a.length());
// 构建正则表达式
StringBuilder patternBuilder = new StringBuilder();
for (String keyword : keywords) {
if (patternBuilder.length() > 0) {
patternBuilder.append("|");
}
patternBuilder.append(Pattern.quote(keyword));
}
// 编译正则表达式
Pattern pattern = Pattern.compile(patternBuilder.toString());
Matcher matcher = pattern.matcher(text);
// 替换匹配到的关键词
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, "<em>" + matcher.group() + "</em>");
}
matcher.appendTail(sb);
return sb.toString();
}
}
代码解释
1.给定的一段话:
String text = "关于发布《放射性废物分类》的公告,放射性物质是有害物质,放射元素会影响人的医生";:定义了一段文本。
2.关键词列表:
String[] keywords = {"放射性废物分类", "放射性物质", "放射性", "放射", "性"};:定义了一个关键词列表。
3.按长度降序排序关键词:
Arrays.sort(keywords, (a, b) -> b.length() - a.length());:按关键词长度降序排序,确保长词优先匹配。
4.构建正则表达式:
StringBuilder patternBuilder = new StringBuilder();:创建一个 StringBuilder 对象来构建正则表达式。
for (String keyword : keywords):遍历关键词列表,将每个关键词添加到正则表达式中。
Pattern.quote(keyword):对关键词进行转义,防止特殊字符影响正则表达式。
5.编译正则表达式:
Pattern pattern = Pattern.compile(patternBuilder.toString());:编译正则表达式。
Matcher matcher = pattern.matcher(text);:创建一个 Matcher 对象,用于在文本中查找匹配项。
6.替换匹配到的关键词:
StringBuffer sb = new StringBuffer();:创建一个 StringBuffer 对象,用于存储替换后的文本。
while (matcher.find()):遍历所有匹配项。
matcher.appendReplacement(sb, "<em>" + matcher.group() + "</em>");:将匹配到的关键词替换为带 <em> 标签的高亮文本。
appendReplacement:从上次替换的位置到这次替换位置之间的字符串加上替换字符串一起追加到StringBuffer里
matcher.appendTail(sb);:将剩余的文本追加到 StringBuffer 中。
打印结果:
System.out.println(highlightedText);:打印高亮后的文本。
关于发布《<em>放射性废物分类</em>》的公告,<em>放射性物质</em>是有害物质,<em>放射</em>元素会影响人的医