java正则匹配 指定内容以外的 内容
2024-09-02 22:26:21
今天,遇到一个需要 匹配出 指定内容以外的 内容的需求。
乍一看,需求貌视很简单啊,直接上 非贪婪模式的 双向零宽断言(有的资料上也叫 预搜索、预查、环视lookaround):
比如,我要匹配 串内所有 大写C打头后接数字(C\d+) 以外的 匹配数据,也就是:非贪婪匹配C\d+和后一个C\d+之间的内容
String test = "C77de3a4Cfg56C78ha123C923aabC123";
String reg = "((?<=C\\d{1,10}+))(.+?)((?=(C\\d+)+))";
Pattern pattern = Pattern.compile(reg);//这里因为反向零宽断言不能出现不固定长度,所以把C\d+处理成了C\d{1,10},见https://www.jb51.net/article/73404.htm
Matcher matcher = pattern.matcher(test);
while (matcher.find()){
System.out.print(matcher.group()+" ");//de3a4Cfg56 ha123 aab
}
再处理下首尾遇到非C\d+的 串,表达式变成:
String reg = "((?<=C\\d{1,10}+)|^)(.+?)((?=(C\\d+)+)|$)";
这里,发现了 不能 处理连续C\d+这 种情况,想了很久,最后只能一个很不爽的实现来搞定了:
String test = "aC77de3a4Cfg56C78C66ha123C923aabC123g";
String reg = "((?<=C\\d{1,10}+)|^)(.+?)((?=(C\\d+)+)|$)";
test = test.replaceAll("("+"C\\d+"+")("+"C\\d+"+")+","$1");//预先将连续的可匹配串替换掉
Pattern pattern = Pattern.compile(reg);//因为
Matcher matcher = pattern.matcher(test);
while (matcher.find()){
System.out.print(matcher.group()+" ");//a de3a4Cfg56 ha123 aab g
}
结果,连续C\d+打头 这种情况还得单独做处理:
String test = "C66C77de3a4Cfg56C78C66ha123C923aabC123g";
String reg = "((?<=C\\d{1,10}+)|^)(.+?)((?=(C\\d+)+)|$)";
test = test.replaceAll("^(C\\d+)+","");//预先将打头连续的可匹配串替换成空
test = test.replaceAll("("+"C\\d+"+")("+"C\\d+"+")+","$1");//预先将串中连续的可匹配串替换掉
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(test);
while (matcher.find()){
System.out.print(matcher.group()+" ");//de3a4Cfg56 ha123 aab g
}
终于大功告成~,最后把上面的逻辑封装成两个工具方法,第一个直接返回匹配串的List,第二个返回匹配 指定内容以外的 内容的List:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern; public class RegUtil {
public static List<String> matches(String src,String reg){
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(src);
List<String> list = new ArrayList<>();
while (matcher.find()){
list.add(matcher.group());
}
return list;
} /**
* 注意,simpleReg正则必须为不带分组的简单正则表达式,至多一个限定符,且只能是+,限定符匹配串串长不超过10字符,例如:C\d+ d+长度不超过10(正), C\d* (误)
* 否则匹配时可能报错
* 匹配 src中匹配了simpleReg以外 的内容
* @param src
* @param simpleReg
* @return
*/
public static List<String> beyondMatches(String src,String simpleReg){
int index = simpleReg.indexOf("+");
String preMatch = index!=-1?new StringBuilder(simpleReg).insert(index,"{1,10}").toString():simpleReg;
return matches(src.replaceAll("^("+simpleReg+")+","").replaceAll("("+simpleReg+")("+simpleReg+")+","$1")
,"((?<="+preMatch+")|^)(.+?)((?=("+simpleReg+")+)|$)");
} public static void main(String[] args) {
String test = "C2C12C21caaCbC12C66C77de3a4Cfg56C78ha123C923aabC123C321";
List<String> result =RegUtil.matches(test,"C\\d+");
for(String m:result){
System.out.print(m+" ");//C2 C12 C21 C12 C66 C77 C78 C923 C123 C321
}
System.out.println();
System.out.println("========");
result =RegUtil.beyondMatches(test,"C\\d+");
for(String m:result){
System.out.print(m+" ");//caaCb de3a4Cfg56 ha123 aab
}
}
}
收功~
最新文章
- Makefile中静态库,动态库的创建和使用以及解压缩命令
- JS获得URL超链接的参数值
- Spire.Doc组件读取与写入Word
- UVA 11987 Almost Union-Find (并查集+删边)
- navigator.sendBeancon方法简介
- Linux下smba服务端的搭建和客户端的使用
- HDU5427
- asp.net文本编辑器(FCKeditor)
- TCP内核源码分析笔记
- 使用ant自动编译安卓项目并签名
- spell checking
- Bootstrap中的strong和em强调标签
- COM学习(三)——COM的跨语言
- 二分partition算法应用
- JS的常用正则表达式 验证密码(转载自用)
- 记一次尴尬的Java应用内存泄露排查
- China MVP Community Connection 2017
- 了解Java内存模型,看完这一篇就够了
- SAP事物代码
- cocoa pods自己的笔记