正则表达式的贪婪匹配问题

转载

学 JSP 的时候拿这个 blog 练手,其它的问题都有了解决方法,可 UBB 代码转换的问题过了 n 个月最后在 CSDN [url=http://community.csdn.net/Expert/topic/3758/3758154.xml]第二次发问[/url]的时候问到了

这是我的问题

[quote]
我的本意是把 [face=宋体]\[b]*[/b][/face] 替换成 [face=宋体]<b>*</b>[/face]

[face=宋体]String str = "\[b]1[/b] 2 \[b]3[/b]";[/face]
[face=宋体]str = str.replaceAll("\\[b\\](.*)\\[\\/b\\]", "<b>$1</b>");[/face]
[face=宋体]out.println(str);[/face]

期望结果是 [face=宋体]<b>1</b> 2 <b>3</b>[/face]

可实际结果 [face=宋体]<b>1[/b] 2 \[b]3</b>[/face]
[/quote]

这个问题在 PHP 里很好解决,因为[url=http://cn2.php.net/manual/en/reference.pcre.pattern.modifiers.php]修正符[/url]里有个 /U (PCRE_UNGREEDY)可以禁止贪婪匹配(写到这的时候才发现这个的描述里有一句“It is not compatible with Perl”)

期间有人给出了符合我所说的,却不是我想要的。即在匹配抓取的时候排除 [ 号,但事实上有时候我还确实要抓取 [ 号,比方说站内文章搜索我使用了 [archive=xxx] 的格式,例如前一篇文章里就有一句“就像以前转过的一篇\[url=[archive=10x]]《发烧症候群》[/url]里面说的那些玩相机的”,Sunmast 给出了个叫[url=http://blog.sunmast.com/sunmast/archive/2005/01/27/1235.aspx]递归消除[/url]的可怕概念,看的头大,也看不明白,用起来也相当复杂,这时候终于有位叫“pigo”的给出了最佳解决方法:
[quote]
[face=宋体]str = str.replaceAll("\\[b\\](.*[color=red][b]?[/b][/color])\\[\\/b\\]", "<b>$1</b>");[/face]
[/quote]

* 和 ? 都是限定符,我还真不知道他俩可以同时使用,查了一下 Java 的 [url=http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html]api 文档[/url],果然有这么一段,只不过当时不明白什么意思,也没有任何例子:

[quote]
[b]Greedy quantifiers[/b] <= 默认都是贪婪匹配
X? X, once or not at all
X* X, zero or more times
X+ X, one or more times
X{n} X, exactly n times
X{n,} X, at least n times
X{n,m} X, at least n but not more than m times

[b]Reluctant quantifiers[/b] <= 这个就是我想要的
X?? X, once or not at all
X*? X, zero or more times
X+? X, one or more times
X{n}? X, exactly n times
X{n,}? X, at least n times
X{n,m}? X, at least n but not more than m times

[b]Possessive quantifiers[/b] <= 不过这个还不明白什么意思
X?+ X, once or not at all
X*+ X, zero or more times
X++ X, one or more times
X{n}+ X, exactly n times
X{n,}+ X, at least n times
X{n,m}+ X, at least n but not more than m times
[/quote]

年前似乎是来不及把这个 blog 改成 jsp 版的了