-
Notifications
You must be signed in to change notification settings - Fork 0
如何用正则表达式求模板字符串替换前后的键值对
eulerlcs edited this page Jul 18, 2017
·
2 revisions
这个问题正是体现正则表达式威力的好例子,所以在这纪录一下,供大家讨论,我把他的问题整理了一下。
有一个模板字符串,占位符(或者也可以叫变量)的格式是${变量名}
,同时有一个把各个占位符替换成真实值之后的文本字符串,请列出占位符和其替换后真实值的键值对。
问题 模板字符串:【工银信用卡】于${startTime}至${endTime}申办奋斗卡,无年费,赢郎平签名排球!详情${link} 文本字符串:【工银信用卡】于昨天至今天申办奋斗卡,无年费,赢郎平签名排球!详情没有
答案
占位符 | 真实值 |
---|---|
${startTime} | 昨天 |
${endTime} | 今天 |
${link} | 没有 |
先写出占位符的正则表达式,然后用Matcher.find()查找模板字符串,Matcher.group()就是占位符。
把占位符替换成正则表达式的子表达式(.*?)
,注意在替换后的正则表达式字符串前后要加 ^
和 $
,理由大家想想。
同样,用Matcher.find()查找文本字符串,Matcher.group()就是替换后的真实值。
/**
* Matcher.group的例子:匹配 字母-数字
*
* <pre>
* group(0):正则表达式的匹配值
* </pre>
*/
@Test
public void test05_00() {
Pattern p = Pattern.compile("([a-z]+)-(\\d+)");
Matcher m = p.matcher("type x-235, type y-3, type zw-465");
while (m.find()) {
System.out.println(m.group());
}
}
@Test
public void test_template_string() {
String tmpl = null;
String text = null;
// test data 1
tmpl = "【工银信用卡】于${startTime}至${endTime}申办奋斗卡,无年费,赢郎平签名排球!详情${link}";
text = "【工银信用卡】于昨天至今天申办奋斗卡,无年费,赢郎平签名排球!详情没有";
// test data 2
tmpl = "a${startTime}b${endTime}";
text = "abbc";
// test data 3
tmpl = "(${startTime}至${endTime}";
text = "(昨天至今天";
System.out.println("模板字符串:" + tmpl);
System.out.println("文本字符串:" + text);
System.out.println();
// 模板字符串中变量的正则表达式
String keyRegex = "\\$\\{.*?\\}";
// 找出模板字符串中变量
List<String> keyList = new ArrayList<>();
{
Pattern p = Pattern.compile(keyRegex);
Matcher m = p.matcher(tmpl);
while (m.find()) {
keyList.add(m.group());
}
}
// 找出文本字符串中替换值集合
List<String> valueList = new ArrayList<>();
{
// **关键想法** 把模板字符串改装成正则表达式
// ** 难点**
// 如果字符串中有元字符,改装后的正则表达式会有语法错误。
// 例子:如果模板字符串中仅存在一个(,该装后的正则表达式会有语法错误。
// 所以在每一个字符前都加\,这样(就变成\(,变成匹配(,符合原意。
// 但是如果模板字符串中仅存在一个t,变成了\t,变成了匹配tab键,又出现了错误。
// 结合以上的说明,我们要有选择的在字符前加\, 我们在非数字字母的字符前加\
String tmplEscape = tmpl.replaceAll("([^\\w])", "\\\\$1");
// 在原始模板字符串中的占位符中的非数字字母的字符前,
// 已经被加\,所以占位符的正则表达式也要做相应的编辑
String keyRegexEscape = "\\\\\\$\\\\\\{.*?\\\\\\}";
String tmplRegex = "^" + tmplEscape.replaceAll(keyRegexEscape, "(.*?)") + "$";
System.out.println("模板字符串改装后的正则表达式:" + tmplRegex);
System.out.println();
Pattern p = Pattern.compile(tmplRegex);
Matcher m = p.matcher(text);
if (m.find()) {
for (int i = 1; i <= m.groupCount(); i++) {
valueList.add(m.group(i));
}
}
}
// 输出结果
if (valueList.isEmpty()) {
System.out.println("the text file format is not correct");
} else {
for (int i = 0; i < keyList.size(); i++) {
System.out.println(keyList.get(i) + "\t\t" + valueList.get(i));
}
}
}