string.replaceAll中的特殊字符
string.replaceAll(String regex, String replacement)中的replacement參數(shù)即替換內(nèi)容中含有特殊字符 $ \ 時(shí),需轉(zhuǎn)義。
Java代碼
1./*
2. * 字符串"$ \"中的$與\字符互換位置
3. */
4.public class SpecialCharReplace {
5. public static void main(String[] args) {
6. String str = "$ \\";
7. /*
8. * string.replaceAll()中的特殊字符 $ 與 \
9. *
10. * 由于 $ 字符在作為替換內(nèi)容時(shí),是一個(gè)特殊字符,指反向引用前面的分組內(nèi)容,所以把
11. * 某字符替換成 $ 字符時(shí),因該在前面加上轉(zhuǎn)義字符 \。
12. * \ 字符就不用說(shuō)了,本身就是轉(zhuǎn)義字符,但為什么在作為替換內(nèi)容時(shí)要使用四個(gè) \ 字符
13. * ,這里又不是用在正則表達(dá)式里?這就是因?yàn)?\ 字符在作為替換內(nèi)容里也是一個(gè)特殊字
14. * 符,它用來(lái)將前面講的 $ 字符進(jìn)行轉(zhuǎn)換的,所以也為特殊字符。以下是replaceAll的
15. * 源碼片斷,從源碼就可以看出 \$ 是兩個(gè)特殊字符
16. *
17. * if (nextChar == '\\') {
18. * cursor++;
19. * nextChar = replacement.charAt(cursor);
20. * result.append(nextChar);
21. * cursor++;
22. * } else if (nextChar == '$') {
23. * // Skip past $
24. * cursor++;
25. * ...
26. * }else {
27. * result.append(nextChar);
28. * cursor++;
29. * }
30. */
31. System.out.println(str.replaceAll("\\$(\\W)\\\\", "\\\\$1\\$"));// \ $
32. }
33.
34.}
/*
* 字符串"$ \"中的$與\字符互換位置
*/
public class SpecialCharReplace {
public static void main(String[] args) {
String str = "$ \\";
/*
* string.replaceAll()中的特殊字符 $ 與 \
*
* 由于 $ 字符在作為替換內(nèi)容時(shí),是一個(gè)特殊字符,指反向引用前面的分組內(nèi)容,所以把
* 某字符替換成 $ 字符時(shí),因該在前面加上轉(zhuǎn)義字符 \。
* \ 字符就不用說(shuō)了,本身就是轉(zhuǎn)義字符,但為什么在作為替換內(nèi)容時(shí)要使用四個(gè) \ 字符
* ,這里又不是用在正則表達(dá)式里?這就是因?yàn)?\ 字符在作為替換內(nèi)容里也是一個(gè)特殊字
* 符,它用來(lái)將前面講的 $ 字符進(jìn)行轉(zhuǎn)換的,所以也為特殊字符。以下是replaceAll的
* 源碼片斷,從源碼就可以看出 \$ 是兩個(gè)特殊字符
*
* if (nextChar == '\\') {
* cursor++;
* nextChar = replacement.charAt(cursor);
* result.append(nextChar);
* cursor++;
* } else if (nextChar == '$') {
* // Skip past $
* cursor++;
* ...
* }else {
* result.append(nextChar);
* cursor++;
* }
*/
System.out.println(str.replaceAll("\\$(\\W)\\\\", "\\\\$1\\$"));// \ $
}
} Matcher對(duì)象的appendReplacement典型應(yīng)用與特殊字符&\的進(jìn)一步分析
問(wèn)題的提出
字符串模板:
String template="尊敬的客戶${customerName}你好!本次消費(fèi)金額${amount},您帳戶${accountNumber}上的余額為${balance},歡迎下次光臨!";
其中以 ${ 開(kāi)始 } 結(jié)尾的為待替換的變量域。
數(shù)據(jù)存放于Map中,key為域名,value為域值。如:
Map--
customerName = 劉明
accountNumber = 888888888
balance = $1000000.00
amount = $1000.00
請(qǐng)編寫(xiě)函數(shù):
public static String composeMessage(String template, Map data) throw Exception
實(shí)現(xiàn)將任意模板字符串中的變量域,按域名替換為data中的域值。
例如,上例替換結(jié)果為:
"尊敬的客戶劉明你好!本次消費(fèi)金額$1000.00,您帳戶888888888上的余額為$1000000.00,歡迎下次光臨!"
注:如果Map中找不到域值,以空字符串""替換。
問(wèn)題的解決
Java代碼
1.public class RegexExam {
2. public static void main(String args[]) {
3. HashMap data = new HashMap();
4. String template = "尊敬的客戶${customerName}你好!本次消費(fèi)金額${amount},"
5. + "您帳戶${accountNumber}上的余額為${balance},歡迎下次光臨!";
6. data.put("customerName", "劉明");
7. data.put("accountNumber", "888888888");
8. data.put("balance", "$1000000.00");
9. data.put("amount", "$1000.00");
10. try {
11. System.out.println(composeMessage(template, data));
12. } catch (Exception e) {
13. e.printStackTrace();
14. }
15. }
16.
17. public static String composeMessage(String template, Map data)
18. throws Exception {
19. String regex = "\\$\\{(.+?)\\}";
20. Pattern pattern = Pattern.compile(regex);
21. Matcher matcher = pattern.matcher(template);
22. /*
23. * sb用來(lái)存儲(chǔ)替換過(guò)的內(nèi)容,它會(huì)把多次處理過(guò)的字符串按源字符串序
24. * 存儲(chǔ)起來(lái)。
25. */
26. StringBuffer sb = new StringBuffer();
27. while (matcher.find()) {
28. String name = matcher.group(1);//鍵名
29. String value = (String) data.get(name);//鍵值
30. if (value == null) {
31. value = "";
32. } else {
33. /*
34. * 由于$出現(xiàn)在replacement中時(shí),表示對(duì)捕獲組的反向引用,所以要對(duì)上面替換內(nèi)容
35. * 中的 $ 進(jìn)行替換,讓它們變成 "\$1000.00" 或 "\$1000000000.00" ,這樣
36. * 在下面使用 matcher.appendReplacement(sb, value) 進(jìn)行替換時(shí)就不會(huì)把
37. * $1 看成是對(duì)組的反向引用了,否則會(huì)使用子匹配項(xiàng)值amount 或 balance替換 $1
38. * ,最后會(huì)得到錯(cuò)誤結(jié)果:
39. *
40. * 尊敬的客戶劉明你好!本次消費(fèi)金額amount000.00,您帳戶888888888上的余額
41. * 為balance000000.00,歡迎下次光臨!
42. *
43. * 要把 $ 替換成 \$ ,則要使用 \\\\\\& 來(lái)替換,因?yàn)橐粋€(gè) \ 要使用 \\\ 來(lái)進(jìn)
44. * 行替換,而一個(gè) $ 要使用 \\$ 來(lái)進(jìn)行替換,因 \ 與 $ 在作為替換內(nèi)容時(shí)都屬于
45. * 特殊字符:$ 字符表示反向引用組,而 \ 字符又是用來(lái)轉(zhuǎn)義 $ 字符的。
46. */
47. value = value.replaceAll("\\$", "\\\\\\$");
48. //System.out.println("value=" + value);
49. }
50. /*
51. * 經(jīng)過(guò)上面的替換操作,現(xiàn)在的 value 中含有 $ 特殊字符的內(nèi)容被換成了"\$1000.00"
52. * 或 "\$1000000000.00" 了,最后得到下正確的結(jié)果:
53. *
54. * 尊敬的客戶劉明你好!本次消費(fèi)金額$1000.00,您帳戶888888888上的
55. * 余額為$1000000.00,歡迎下次光臨!
56. *
57. * 另外,我們?cè)谶@里使用Matcher對(duì)象的appendReplacement()方法來(lái)進(jìn)行替換操作,而
58. * 不是使用String對(duì)象的replaceAll()或replaceFirst()方法來(lái)進(jìn)行替換操作,因?yàn)?nbsp;
59. * 它們都能只能進(jìn)行一次性簡(jiǎn)單的替換操作,而且只能替換成一樣的內(nèi)容,而這里則是要求每
60. * 一個(gè)匹配式的替換值都不同,所以就只能在循環(huán)里使用appendReplacement方式來(lái)進(jìn)行逐
61. * 個(gè)替換了。
62. */
63. matcher.appendReplacement(sb, value);
64. System.out.println("sb = " + sb.toString());
65. }
66. //最后還得要把尾串接到已替換的內(nèi)容后面去,這里尾串為“,歡迎下次光臨!”
67. matcher.appendTail(sb);
68. return sb.toString();
69. }
70.}
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。