今天在项目中遇到这样一个需求:
要求把一段HTML代码中的注释里的某类表达式替换掉,而在注释外的这类表达式不需要替换,例如:
%(/images/a.jpg)
<!-- <image src="%(/images/a.jpg)"> -->
%(/images/a.jpg)
<!-- <image src="%(/images/b.jpg)"> <image src="%(/images/c.jpg)"> -->
%(/images/a.jpg)
其中,在注释内的%(/images/a.jpg)要替换成${contextPath}/images/a.jpg
替换后应该是这样的:
%(/images/a.jpg)
<!-- <image src="${contextPath}/images/a.jpg"> -->
%(/images/a.jpg)
<!-- <image src="${contextPath}/images/b.jpg"> <image src="${contextPath}/images/c.jpg"> -->
%(/images/a.jpg)
经过一番研究,深入了解了一下greedy、reluctant和possessive这些量词的区别(可以参考一下),以及Special constructs (non-capturing)的作用(以前也没对REGEX去太多研究,只用点简单的),留下代码,以供日后查阅
/**
* Replace special symbol in html comments, like "<!-- %(/images/a.jpg) -->"
* @param text
* @return
*/
protected String replaceSpecialSymbolInComments(String text) {
log.debug("call replaceSpecialSymbolInComments(" + text + ")");
if (text == null) return text;
String commentRegex = "(?s)(?<=<!--).*?(?=-->)";
String specialRegex01 = "\\%\\((.*?)\\)";
Pattern commentPattern = Pattern.compile(commentRegex);
Pattern specialPattern01 = Pattern.compile(specialRegex01);
Matcher commentMatcher = commentPattern.matcher(text);
StringBuilder sb = new StringBuilder(text);
int offset = 0;
while (commentMatcher.find()) {
log.debug("comment match result: " + commentMatcher.group());
int commentMatchStart = offset + commentMatcher.start();
int commentMatchEnd = offset + commentMatcher.end();
log.debug(commentMatchStart + " -- " + commentMatchEnd);
Matcher specialMatcher01 = specialPattern01.matcher(commentMatcher.group());
while (specialMatcher01.find()) {
commentMatchStart = offset + commentMatcher.start();
commentMatchEnd = offset + commentMatcher.end();
log.debug("special match result01: " + specialMatcher01.group());
log.debug("special match result01 should be: " + "${contextPath}" + specialMatcher01.group(1));
int specialMatchStart01 = specialMatcher01.start();
int specialMatchEnd01 = specialMatcher01.end();
offset += ("${contextPath}" + specialMatcher01.group(1)).length() - specialMatcher01.group(0).length();
sb.replace(commentMatchStart + specialMatchStart01, commentMatchStart + specialMatchEnd01, "");
sb.insert(commentMatchStart + specialMatchStart01, "${contextPath}" + specialMatcher01.group(1));
}
log.debug("temp result: " + sb.toString());
}
return sb.toString();
}
附录参考:引用 http://zzg810314.iteye.com/blog/194643
greedy、reluctant和possessive量词的区别
greedy、reluctant和possessive量词之间有微妙的区别。
greedy量词被看作“贪婪的”,因为它们在试图搜索第一个匹配之前读完(或者说吃掉)整个输入字符串。如果第一个匹配尝试(整个输入字符串)失败,匹配器就会在输入字符串中后退一个字符并且再次尝试,重复这个过程,直到找到匹配或者没有更多剩下的字符可以后退为止。根据表达式中使用的量词,它最后试图匹配的内容是1 个或者0个字符。
但是,reluctant量词采取相反的方式:它们从输入字符串的开头开始,然后逐步地一次读取一个字符搜索匹配。它们最后试图匹配的内容是整个输入字符串。
最后,possessive量词总是读完整个输入字符串,尝试一次(而且只有一次)匹配。和greedy量词不同,possessive从不后退,即使这样做能允许整体匹配成功。
为了演示,我们分析输入字符串xfooxxxxxxfoo:
Enter your regex: .*foo // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.
Enter your regex: .*?foo // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.
Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.
第一个例子使用greedy量词.*搜索“任何内容”零次或者多次,后面是字母f、o、o。因为是greedy量词,所以表达式的.*部分首先读完整个字符串。这样,整个表达式不会成功,因为最后三个字母(“f”“o”“o”)已经被消耗了。所以匹配器缓慢地一次后退一个字母,一直后退到最右侧出现“foo”为止,这里匹配成功并且搜索停止。
但是第二个例子使用的量词是reluctant量词,所以它首先消耗“无内容”。因为“foo”没有出现在字符串的开头,所以迫使它消耗掉第一个字母(x),这样就在索引0和4的位置触发第一个匹配。我们的测试示例继续处理,直到输入字符串耗尽为止。它在索引4和13找到了另一个匹配。
第三个例子找不到匹配,因为是possessive量词。这种情况下,.*+消耗整个输入字符串,在表达式的结尾没有剩下满足“foo”的内容。possessive量词用于处理所有内容,但是从不后退的情况;在没有立即发现匹配的情况下,它的性能优于功能相同的greedy量词。
分享到:
相关推荐
本文写作时,一个包含了用正则表达式进行文本处理的Java规范需求(Specification Request)已经得到认可,你可以期待在JDK的下一版本中看到它。 然而,如果现在就需要使用正则表达式,又该怎么办呢?你可以从Apache...
正则表达式,正则表达式,正则表达式 正则表达式 正则表达式 正则表达式 正则表达式 正则表达式 正则表达式
常用正则表达式 正则表达式 常用正则表达式 正则表达式
正则表达式.rar正则表达式.rar正则表达式.rar正则表达式.rar
《学习正则表达式》从正则表达式的基本概念讲...此外,书中各在线和桌面工具一应俱全,并介绍了进阶参考资料,是一本不可多得的正则表达式入门好书。《学习正则表达式》适合对正则表达式感兴趣的程序员和互联网从业者。
3、选择排除规则,一、按正则表达式把源码中符合正则的删除;二、按正则表达式把源码中符合正则的找出;三、符合正则表达式的显示True 4、选择是否不区分大小写(RegexOptions.IgnoreCase),单行模式...
正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式...
《正则表达式经典实例》旨在教会读者很多新的技巧以及如何避免语言特定的陷阱,读者可以通过《正则表达式经典实例》提供的实例解决方案库来解决实践中的复杂问题。 《正则表达式经典实例》:每个程序员都会遇到...
常用正则表达式大全: 匹配中文字符的正则表达式 匹配空白行的正则表达式 匹配HTML标记的正则表达式 匹配Email地址的正则表达式 匹配网址URL的正则表达式 匹配国内电话号 匹配中国邮政编码 匹配身份证 匹配ip地址 ...
正则表达式正则表达式正则表达式正则表达式 验证程序
Java正则表达式Java正则表达式Java正则表达式Java正则表达式
正则表达式帮助 有用的正则表达式帮助 有用的正则表达式帮助 有用的正则表达式帮助 有用的
正则表达式日期校验 正则表达式日期校验 正则表达式日期校验
正则表达式 正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式
正则表达式总结正则表达式总结正则表达式总结正则表达式总结正则表达式总结正则表达式总结
UE正则表达式、UE正则表达式
正则表达式速查 正则表达式举例 正则表达式学习 (4页A4纸)
正则表达式 详解 基础 正则表达式之道(A Tao of Regular Expressions)
正则表达式正则表达式正则表达式正则表达式正则表达式正则表达式
常用正则表达式大全.txt常用正则表达式大全.txt常用正则表达式大全.txt常用正则表达式大全.txt常用正则表达式大全.txt