伪高亮方法:
/**
* 高亮描述
*
* @param keyword
* @param content
*/
public static String highlight(String keyword, String content) {
keyword = KeywordEncodeUtil.filter(keyword);
if (StringUtils.isBlank(keyword) || StringUtils.isBlank(content)) {
return "";
}
char[] charsKey = keyword.toCharArray();
char[] charsText = content.toCharArray();
String[] strsText = new String[charsText.length];
for (int i = 0; i < charsText.length; i++) {
strsText[i] = String.valueOf(charsText[i]);
for (char ch : charsKey) {
if (Character.toLowerCase(charsText[i]) == ch || Character.toUpperCase(charsText[i]) == ch) {
strsText[i] = "<em>" + charsText[i] + "</em>";
}
}
}
content = StringUtils.join(strsText);
StringBuilder sb = new StringBuilder(content);
try {
String reg = "^\\s*<em>(\\S)</em>([^<])";
Pattern pat = Pattern.compile(reg);
Matcher mat = pat.matcher(sb);
while (mat.find()) {
sb.replace(mat.start(),mat.end(),mat.group(1)+mat.group(2));
}
reg = "([^>])<em>(\\S)</em>(?!<)";
pat = Pattern.compile(reg);
mat = pat.matcher(sb);
while (mat.find()) {
sb.replace(mat.start(),mat.end(),mat.group(1)+mat.group(2));
mat = pat.matcher(sb);
}
} catch (Exception e) {
System.out.println("正则过滤失败!");
}
return sb.length()>0?sb.toString():content;
}
测试文本:
<em>广</em>sf<em>广</em>s<em>广</em>sdf<em>广</em><em>州</em>ssdf<em>广</em>
规则:去掉单字的em标签
注意点:
1.如上测试文本过滤,f<em>广</em>会出现多次,相连的<em>则要求保留
2.(?!<)这种写法,匹配右侧不是<。如果直接[^<]则只能匹配到一个,像这种 f<em>广</em>s<em>广</em>s 第二个表达式会匹配不出来。
3.matcher获取匹配表达式的在匹配字符串的起始index和结束index.
小括号的作用
分类 代码/语法 说明
捕获
(exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释
(?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读
要特别注意的是,零宽断言是不占用位置的,也就是说,匹配结果里是不会返回它的。
(?:exp) 既不捕获匹配的文本,也不给此分组分配组号,这个东西到底有什么用呢?
(?:exp) 非捕获组,匹配exp的内容,但不捕获到组里