java正则匹配及替换的一点思考
2016-05-16 23:30
543 查看
Java语言String类提供了简单的relace,replaceAll等方法:
在很多简单的情况下,这几个方法就能满足使用了。但是较为复杂的的情况下就不能仅靠这几个方法解决问题了。由于在实际工作中遇到的问题,引发如下的思考:
一个字符串含”hello world”,把hello 替换为hello hello,调用replaceAll会导致无穷死循环吗?java显然不会导致这样的问题发生,如果那样的话应该没人用java了,答案是不会,通过看replaceAll的源码了解其算法,在String内部,执行replaceAll的时候是在原位置执行替换的,有记录起始位置的指针,不会导致死循环,但是把hello替换为”hello hello”(多加几个空格),是会导致结果能出现3个hello的,这显然不是我们期望的结果。
这其实要实现替换的新旧字符串存在一定包含关系的替换问题,比如一个文件里有很多ip,我们要把他替换,比如10.10.10.101替换成10.10.10.10,这里后者是前者的一个字串,用简单的replcae和replaceAll不能很好的解决问题。
要想面对特殊情况也能正确的替换,最好是新建一个StringBuffer,逐字符遍历被匹配替换的string,把最新的结果保存在StringBugffer,最后才用StringBuffer返回结果。其实java的正则实现了这样的方法,涉及到Match类,一个例子程序:
用到了Match类的group、appendReplacement、appendTail等方法,这几个方法应该就是用于比较复杂的匹配及替换的场景的吧。
在很多简单的情况下,这几个方法就能满足使用了。但是较为复杂的的情况下就不能仅靠这几个方法解决问题了。由于在实际工作中遇到的问题,引发如下的思考:
一个字符串含”hello world”,把hello 替换为hello hello,调用replaceAll会导致无穷死循环吗?java显然不会导致这样的问题发生,如果那样的话应该没人用java了,答案是不会,通过看replaceAll的源码了解其算法,在String内部,执行replaceAll的时候是在原位置执行替换的,有记录起始位置的指针,不会导致死循环,但是把hello替换为”hello hello”(多加几个空格),是会导致结果能出现3个hello的,这显然不是我们期望的结果。
这其实要实现替换的新旧字符串存在一定包含关系的替换问题,比如一个文件里有很多ip,我们要把他替换,比如10.10.10.101替换成10.10.10.10,这里后者是前者的一个字串,用简单的replcae和replaceAll不能很好的解决问题。
要想面对特殊情况也能正确的替换,最好是新建一个StringBuffer,逐字符遍历被匹配替换的string,把最新的结果保存在StringBugffer,最后才用StringBuffer返回结果。其实java的正则实现了这样的方法,涉及到Match类,一个例子程序:
public static boolean update(String file,Map<String,String> changes){ try { Path path = Paths.get(file); if(Files.notExists(path)){ System.out.println(String.format("file %s does does not exist",file)); return false; } if(!Files.isWritable(path)){ System.out.println(String.format("can not write file %s", file)); return false; } List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8); List<String> newLines = new ArrayList<>(); Iterator<String> iterator = lines.iterator(); while(iterator.hasNext()){ Matcher matcher = PATTERN.matcher(iterator.next()); StringBuffer sb = new StringBuffer(); while(matcher.find()){ String str = matcher.group(); if(ipChanges.containsKey(str)){ matcher.appendReplacement(sb,changes.get(str)); } } matcher.appendTail(sb); newLines.add(new String(sb)); } Files.write(path, newLines, StandardCharsets.UTF_8); } catch (IOException e) { System.out.println(String.format("IO exception happened when modify file %s",file)); return false; } System.out.println(String.format("success modified file %s",file)); return true; }
用到了Match类的group、appendReplacement、appendTail等方法,这几个方法应该就是用于比较复杂的匹配及替换的场景的吧。
相关文章推荐
- java 位运算与运算基础
- 开发笔记--java.lang.OutOfMemoryError: PermGen space异常处理
- Struts2中通过超链接传参数要注意的问题
- SpringMVC添加spring-security静态资源加载问题
- java Cache框架
- Eclipse输入任意字母或指定字符出现提示框
- [javaSE] 数组(排序-冒泡排序)
- RxJava之调度器(Schedulers)
- java 面向对象练习题2
- JAVA实现数据库数据导入/导出到Excel(POI技术)
- C#和Java中的i=i++问题分析与备忘
- MyEclipse/Eclipse 优化
- 学习SpringMVC(七)之处理模型数据
- Spring学习(一)---IoC介绍(2)
- Java基础要点总结
- Java Web 从入门到精通(明日科技)
- 基于JAVA反射的Spring原理----例子
- java中int,char,string之间的相互转换方法
- #码神心得_02# java基础知识
- Java面向对象之抽象类