java正则匹配及替换的一点思考

来源:互联网 发布:通达信软件使用说明书 编辑:程序博客网 时间:2024/05/16 08:29

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等方法,这几个方法应该就是用于比较复杂的匹配及替换的场景的吧。

0 0