今天,遇到一个需要 匹配出 指定内容以外的 内容的需求。

乍一看,需求貌视很简单啊,直接上 非贪婪模式的 双向零宽断言(有的资料上也叫 预搜索、预查、环视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
}
}
}

  

收功~

最新文章

  1. Makefile中静态库,动态库的创建和使用以及解压缩命令
  2. JS获得URL超链接的参数值
  3. Spire.Doc组件读取与写入Word
  4. UVA 11987 Almost Union-Find (并查集+删边)
  5. navigator.sendBeancon方法简介
  6. Linux下smba服务端的搭建和客户端的使用
  7. HDU5427
  8. asp.net文本编辑器(FCKeditor)
  9. TCP内核源码分析笔记
  10. 使用ant自动编译安卓项目并签名
  11. spell checking
  12. Bootstrap中的strong和em强调标签
  13. COM学习(三)——COM的跨语言
  14. 二分partition算法应用
  15. JS的常用正则表达式 验证密码(转载自用)
  16. 记一次尴尬的Java应用内存泄露排查
  17. China MVP Community Connection 2017
  18. 了解Java内存模型,看完这一篇就够了
  19. SAP事物代码
  20. cocoa pods自己的笔记

热门文章

  1. UEFI Shell --常用命令解释
  2. md5函数
  3. masonry中的make,remake,update
  4. 浅析常见的 Web 安全预防
  5. Element Form表单实践(上)
  6. ORACLE重做日志小结
  7. java 面向对象面试题,问答题,构造方法,抽象类,继承,多态,接口,异常总结;
  8. dockerfile文档的相关参数
  9. 机器学习决策树ID3算法,手把手教你用Python实现
  10. 苏浪浪 201771010120《面向对象程序设计(java)》第八周学习总结