您的位置:首页 > 编程语言 > Java开发

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类,一个例子程序:

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等方法,这几个方法应该就是用于比较复杂的匹配及替换的场景的吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: