今天公司线上出了一个bug,发送短信的内容中,点位符替换错误,原因就是字符串的replace方法
{$var}您好:您办理的{$var}业务已到期,请处理!
看下原代码处理
@Test
public void testReplace() {
String context = "{$var}您好:您办理的{$var}业务已到期,请处理!";
String[] param = {"周星星", "人人有功练"};
int i = 0;
while(context.contains(PRE_BRACES)){
int index = context.indexOf(PRE_BRACES);
String argName = context.substring(index , context.indexOf(SUF_BRACES) + 1);
context = context.replace(argName ,String.valueOf( param[i]));
i++;
}
System.out.println(context);
}
看下输出结果:
周星星您好:您办理的周星星业务已到期,请处理!
很遗憾,不是我们想要,而这就是因为对replace理解错误导致(原以为只会替换第一个)
那我们看看replace正确的用法及相关的replaceAll
看看api解释
replace
public String replace(char oldChar,
char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
如果 oldChar 在此 String 对象表示的字符序列中没有出现,则返回对此 String 对象的引用。否则,创建一个新的 String 对象,它所表示的字符序列除了所有的 oldChar 都被替换为 newChar 之外,与此 String 对象表示的字符序列相同。
示例:
"mesquite in your cellar".replace('e', 'o')
returns "mosquito in your collar"
"the war of baronets".replace('r', 'y')
returns "the way of bayonets"
"sparring with a purple porpoise".replace('p', 't')
returns "starring with a turtle tortoise"
"JonL".replace('q', 'x') returns "JonL" (no change)
参数:
oldChar - 原字符。
newChar - 新字符。
返回:
一个从此字符串派生的字符串,它将此字符串中的所有 oldChar 替代为 newChar。ss
再看看replaceAll
replaceAll
public String replaceAll(String regex,
String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的 正则表达式的子字符串。
调用此方法的 str.replaceAll(regex, repl) 形式与以下表达式产生的结果完全相同:
Pattern.compile( regex ).matcher( str ).replaceAll( repl )
注意,在替代字符串中使用反斜杠 (\) 和美元符号 ($) 与将其视为字面值替代字符串所得的结果可能不同;请参阅 Matcher.replaceAll。如有需要,可使用 Matcher.quoteReplacement(java.lang.String) 取消这些字符的特殊含义。
参数:
regex - 用来匹配此字符串的正则表达式
replacement - 用来替换每个匹配项的字符串
返回:
所得 String
发现2个方法实现的效果是一样的,但是replaceAll可以用正则表达式,而replace只是普通的字符
通过实例比较一下
String str1 = "{$var}您好:您办理的{$var}业务已到期,请处理!";
String str2 = "{$var}您好:您办理的{$var}业务已到期,请处理!";
// 普通文本
str1 = str1.replace("{$var}", "周星星");
// 必须是正则表达式,否则编译器会报错
str2 = str2.replaceAll("\\{\\$var\\}", "周星星");
System.out.println(str1);
System.out.println(str2);
转出结果:
周星星您好:您办理的周星星业务已到期,请处理!
周星星您好:您办理的周星星业务已到期,请处理!再看一下正则替换的例子:
String str3 = "aaabbbcccddd111222";
String str4 = "aaabbbcccddd111222";
// 将所有的"d"替换为"f"
str3 = str3.replace("d", "f");
// 将所有的数字替换为"f"
str4 = str4.replaceAll("\\d", "f");
System.out.println(str3);
System.out.println(str4);
输出结果:
aaabbbcccfff111222
aaabbbcccdddffffff,相信区别一目了然了!
最后再提供一下,刚才问题的一个解决方法(非最优方法)
/**
* 根据指定的字符参数替换变量
*
* @param context 源字符
* @param params 参数
* @param preBraces 分割符
* @param subBraces 分割符
* @return
*/
public static String replaceAll(String context, Object[] params, String preBraces, String subBraces) {
StringBuilder sb = new StringBuilder();
int i = 0;
String lastContext = StringUtils.EMPTY;
while (context.contains(preBraces)) {
String subContext = context.substring(NumberConstantEnum.ZERO.getIntValue(), context.indexOf(preBraces));
context = context.substring(context.indexOf(subBraces) + 1, context.length());
lastContext = context;
sb.append(subContext);
sb.append(params[i]);
i++;
}
sb.append(lastContext);
return sb.toString();
}