javareplaceall正则_placeAll⽅法详析(正则妙⽤)前⾔
我通常是不太关⼼代码的具体实现的,因为我的开发语⾔很杂,倾向于⼀些最简单通⽤的⽅式去解决。今⼉不⼩⼼在⾥看到⼀位朋友发了下⾯的java代码,感觉⾃⼰还是很局限很⽆知的:
String str1 = "createTime";
String str2 = "createTimeAt";
String regex = "([A-Z])+";
System.out.placeAll(regex, "_$1").toLowerCase());
System.out.placeAll(regex, "_$1").toLowerCase());
//result
//create_time
//create_time_at
通过输出可以看到,这段代码的作⽤是把驼峰命名格式的字符串替换成下划线分割,这个功能⽐较简单,但是吸引我的却是他的代码。
"createTime".replaceAll("([A-Z]+)","_$1")
java replace方法这⾏代码简单的很,就是调⽤了String类的replaceAll⽅法,⽅法的第⼀个参数是正则表达式,第⼆个参数是将要被替换成的新值。
让我惊奇的是他代码中,replaceAll的第⼆个参数,也就是JDK⽂档中名为replacement的参数,竟然是_$1。这是什么⿁?还⽀持类似占位符这样的东西?我⼀直都不知道。
问题探索
由于之前研究过⼀段正则表达式,通过观察replaceAll的第⼀个参数([A-Z]+),我猜想,这个应该是⽤到了正则表达式的分组,对应JDK 中,就是Matcher类的group()⽅法。
在Linux的Sed命令上,就使⽤&进⾏了⼀些替换,道理应该是相通的。
于是看了下placeAll⽅法是如何实现的。JDK:
public String replaceAll(String regex, String replacement) {
return Patternpile(regex).matcher(this).replaceAll(replacement);
}
哦,原来它底层就是⽤了Matcher,只不过⽤的是Matcher⾃⼰的replaceAll⽅法。
去看它的⽂档,这个⽅法的参数果然有⿁,看下⾯实现代码。
public String replaceAll(String replacement) {
reset();
boolean result = find();
if (result) {
StringBuilder sb = new StringBuilder();
do {
appendReplacement(sb, replacement);
result = find();
} while (result);
appendTail(sb);
String();
}
String();
}
⾥⾯关键的部分就是⽂档中说的appendReplacement⽅法,然后可以看到详细的描述⽂档。
看到这⾥明⽩了,原来这个⽅法的replacement参数可以通过$字符来指代Matcher通过正则匹配得到的分组,⽀持name和number 两种⽅式,这⾥对应的就是Matcher类的group(name)和group(int)两个⽅法。
结论
1、String的replaceAll⽅法实际上是通过Matcher类的replaceAll()⽅法实现的。
2、Matcher类的replaceAll⽅法⼜是通过调⽤appendReplacement⽅法实现替换逻辑
3、Matcher类的appendReplacement⽅法的replacement参数⽀持通过$符号来指代Matcher匹配的分组
下⾯这串代码,就是使⽤Matcher类分组的⼀个最佳实践。
String data = "哈哈哈,xjjdog的⼿机号码是:12345678901,你会打给我吗";
//通过Matcher的分组功能,可以提取出上⾯字符串中的⼿机号
Matcher matcher = Patternpile(".*(xjjdog的⼿机号码是:([0-9]{11}))").matcher(data);
while (matcher.find()) {
System.out.println("G0:" + up(0));
System.out.println("G1:" + up(1));
System.out.println("G2:" + up(2));
}
//result
//G0:哈哈哈,xjjdog的⼿机号码是:12345678901
//G1:xjjdog的⼿机号码是:12345678901
//G2:12345678901
group(0)表⽰整个字符串
group(1)表⽰第⼀个匹配的,上⾯的例⼦中就是(我的⼿机号码是:([0-9]{11}))部分
group(2)表⽰第⼆个匹配的,上⾯的例⼦中就是([0-9]{11})部分
使⽤分组可以⽤来提取字符串中的⽬标字符串值,很好⽤!
⼏个例⼦
下⾯是⼏个例⼦,⼤家可以触类旁通。
驼峰转下划线命名
public static String camelToUnderline(String camelName) {
placeAll("([A-Z]+)", "_$1").toLowerCase();
}
下划线转驼峰
这个稍微⿇烦点,是模仿者placeAll⽅法写的。
public static String underlineToCamel(String underlineName) {
Matcher matcher = Patternpile("(_[a-z]{1})").matcher(underlineName);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
String replacement = up(1);
matcher.appendReplacement(result, place("_", "").toUpperCase());
}
matcher.appendTail(result);
String();
}
另外,Mybatis Generator插件源码中的也提供了类似⽅法(CamelCaseString),这⾥做了下简单修改public static String getCamelCaseString(String inputString) {
StringBuilder sb = new StringBuilder();
boolean nextUpperCase = false;
for (int i = 0; i < inputString.length(); i++) {
char c = inputString.charAt(i);
switch (c) {
case '_':
case '-':
case '@':
case '$':
case '#':
case ' ':
case '/':
case '&':
if (sb.length() > 0) {
nextUpperCase = true;
}
break;
default:
if (nextUpperCase) {
sb.UpperCase(c));
nextUpperCase = false;
} else {
sb.LowerCase(c));
}
break;
}
}
String();
}
没有复杂的正则参与,速度显⽽快了不少。
总结
看⼀些优秀的开源代码,确实能够了解到⼀些实⽤的技巧。这⽐起⾃⼰费劲⼼⼒重复制造⼀些轮⼦,要⾼效的多。时间要⽤在⼑刃上,但不是⽤来切⾖腐。
好了,以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,谢谢⼤家对脚本之家的⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论