项目场景:
Matcher类是常用的正则匹配的类,今天用到了find方法,使用过程中出现了一些细节的小问题,现在记录下来方便初学者借鉴。
问题描述
先看下面这段代码:
//待匹配字符串
String inputStr = "1 Num 2 Num 3";
//匹配条件
String target = "Num";
Pattern p = Pattern.compile(target);
Matcher m = p.matcher(inputStr);
//连续三次调用find方法
System.out.println(m.find());
System.out.println(m.find());
System.out.println(m.find());
上网了解find方法时发现很多文章说一个matcher对象和find方法是一一对应的,那么同一个Matcher对象连续调用三次find方法,三次输出结果应该为“true、true、true”,但是实际运行程序会发现,输出结果为“true、true、false”
原因分析:
事实上,matcher对象与find方法一一对应的说法是不准确的,find方法在第一次运行时其实是匹配到了字符串中遇到的第一个命中字符串,第二次运行时,find方法不会重新从头开始匹配,而是会从上一次匹配命中的下一个字符开始,因此,再看前面的代码,前两次调用find方法后,第三次调用时会从第二个“Num”后的空格开始匹配,而后面没有“Num”了,所以返回了“false”
拓展:
这里结合业务,记录一种循环匹配,并替换目标字符串的方法,直接看代码:
String inputStr = "1 Num 2 Num 3 Num 4";
String target = "Num";
String replaceStr = "+";
Pattern p = Pattern.compile(target);
Matcher m;
//如果想在循环之前判断字符串中是否有匹配命中的字符,可以调用find后用reset重置Matcher对象
if(m.find()){
...//其他逻辑
}
m.reset();
StringBuffer tempStr = new StringBuffer();
//sb:""
for(m = p.matcher(inputStr); m.find();){
m.appendReplacement(sb, replaceStr);//将从开头到本次匹配命中的字符,替换后追加给sb
//sb:第一次:"1 +",第二次:"1 + 2 +",第三次:"1 + 2 + 3 +"
//第四次m.find()为false结束循环
}
m.appendTail(sb);//将剩下的未匹配的字符串追加给sb,得到完整的匹配替换后的字符串
//sb:"1 + 2 + 3 + 4"