关于replaceAll

在开发中遇到的问题,问题已经解决了,但是深层原因还没搞懂,先记录下来慢慢沉淀!

java.lang.String.replaceAll(String regex,String replacement)

以下用几个demo来说明:

public class Test {
	public static void main(String args[]){
		String comment = "600444abc";
		String a= "600444";
		String key = "*abc";//**.?+$^()[]{}
		
		String b = comment.replaceAll(a+ "|" + key, "<a>" + a + key +"</a>");
		System.out.println(b);
	}
}

运行结果:


 问题原因:replaceAll的第一个参数是一个正则表达式,而变量key中包含正则表达式的特殊字符*,于是这个*不会被当成key的内容,而是当成了正则表达式的特殊字符,由于在正则表达式中*是不能放在表达式的开始位置,于是抛错了。

将正则表达式里所有特殊字符做处理后的demo如下:

public class Test {
	public static void main(String args[]){
		String comment = "600444abc";
		String a= "600444";
		String key = "*abc";//**.?+$^()[]{}
		
		String b = comment.replaceAll(Escape(a)+ "|" + Escape(key), "<a>" + a + key +"</a>");
		System.out.println(b);
	}
	
	private static String Escape(String a){
		a = a.replaceAll("\\\\", "\\\\\\\\");
		a = a.replaceAll("\\*", "\\\\*");
		a = a.replaceAll("\\.", "\\\\.");
		a = a.replaceAll("\\?", "\\\\?");
		a = a.replaceAll("\\+", "\\\\+");
		a = a.replaceAll("\\$", "\\\\\\$");
		a = a.replaceAll("\\^", "\\\\^");
		a = a.replaceAll("\\[", "\\\\[");
		a = a.replaceAll("\\]", "\\\\]");
		a = a.replaceAll("\\(", "\\\\(");
		a = a.replaceAll("\\)", "\\\\)");
		a = a.replaceAll("\\{", "\\\\{");
		a = a.replaceAll("\\}", "\\\\}");
		a = a.replaceAll("\\|", "\\\\|");
		return a;
	}
}

运行结果:

通过特殊字符转义后运行正常,再一一测试其他特殊字符.?+$^|\()[]{},发现仅$通不过,demo如下:

public class Test {
	public static void main(String args[]){
		String comment = "600444abc";
		String a= "600444";
		String key = "$abc";//**.?+$^()[]{}
		
		String b = comment.replaceAll(Escape(a)+ "|" + Escape(key), "<a>" + a + key +"</a>");
		System.out.println(b);
	}
	
	private static String Escape(String a){
		a = a.replaceAll("\\\\", "\\\\\\\\");
		a = a.replaceAll("\\*", "\\\\*");
		a = a.replaceAll("\\.", "\\\\.");
		a = a.replaceAll("\\?", "\\\\?");
		a = a.replaceAll("\\+", "\\\\+");
		a = a.replaceAll("\\$", "\\\\\\$");
		a = a.replaceAll("\\^", "\\\\^");
		a = a.replaceAll("\\[", "\\\\[");
		a = a.replaceAll("\\]", "\\\\]");
		a = a.replaceAll("\\(", "\\\\(");
		a = a.replaceAll("\\)", "\\\\)");
		a = a.replaceAll("\\{", "\\\\{");
		a = a.replaceAll("\\}", "\\\\}");
		a = a.replaceAll("\\|", "\\\\|");
		return a;
	}
}

运行结果:


百思不得其解,当key无论被赋什么值,无论这些特殊字符怎么组合只要没有$就可以通过。发现把replaceAll的第一个参数的“或”去掉,$符号就可以通过了。但是在业务逻辑中”或“是必须要使用的。

String b = comment.replaceAll(Escape(a)+ "" + Escape(key), "<a>" + a + key +"</a>");//$可以通过

后来小组经理告诉我可以用:StringUtils.replace(String text, String searchString, String replacement);这个方法也可以替换,StringUtils属于org.apache.commons.lang.StringUtils包。但是这个replace没有正则表达式,达不到”或“的业务需要,如果通过两次raplace那么第一次替换的结果会影响到第二次替换,不符合需求。

后来发现replaceAll的第二个参数也需要特殊字符转义,解决demo如下:

public class Test {
	public static void main(String args[]){
		String comment = "600444abc";
		String a= "600444";
		String key = "$abc";//**.?+$^()[]{}
		
		String b = comment.replaceAll(Escape(a)+ "|" + Escape(key), Escape("<a>" + a + key +"</a>"));
		System.out.println(b);
	}
	
	private static String Escape(String a){
		a = a.replaceAll("\\\\", "\\\\\\\\");
		a = a.replaceAll("\\*", "\\\\*");
		a = a.replaceAll("\\.", "\\\\.");
		a = a.replaceAll("\\?", "\\\\?");
		a = a.replaceAll("\\+", "\\\\+");
		a = a.replaceAll("\\$", "\\\\\\$");
		a = a.replaceAll("\\^", "\\\\^");
		a = a.replaceAll("\\[", "\\\\[");
		a = a.replaceAll("\\]", "\\\\]");
		a = a.replaceAll("\\(", "\\\\(");
		a = a.replaceAll("\\)", "\\\\)");
		a = a.replaceAll("\\{", "\\\\{");
		a = a.replaceAll("\\}", "\\\\}");
		a = a.replaceAll("\\|", "\\\\|");
		return a;
	}
}
运行结果:


再后来发现这样也跟上面的代码达到相同结果,demo如下:

import org.apache.commons.lang.StringUtils;

public class Test {
	public static void main(String args[]){
		String comment = "600444abc";
		String a= "600444";
		String key = "$**.?+$^()[]{}abc\\";//**.?+$^()[]{}
		String[] searchList = {a,key};
		String replacementList[] = {"<a>" + a + key +"</a>","<a>" + a + key +"</a>"};
		//String b = comment.replaceAll(Escape(a)+ "|" + Escape(key), Escape("<a>" + a + key +"</a>"));
		//System.out.println(b);
		String c = StringUtils.replaceEach(comment, searchList, replacementList);
		System.out.println(c);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值