Java正则表达式实例详解

sun的教程

http://java.sun.com/developer/technicalArticles/releases/1.4regex/

创建正则表达式

你可以从比较简单的东西入手学习正则表达式。要想全面地掌握怎样构建正则表达式,可以去看JDK文档的java.util.regex的Pattern类的文档。

字符 B 字符B xhh 16进制值0xhh所表示的字符 uhhhh 16进制值0xhhhh所表示的Unicode字符 Tab
换行符
回车符 f 换页符 e Escape

正则表达式的强大体现在它能定义字符集(character class)。下面是一些最常见的字符集及其定义的方式,此外还有一些预定义的字符集:

字符集 . 表示任意一个字符 [abc] 表示字符a,b,c中的任意一个(与a|b|c相同) [^abc] 除a,b,c之外的任意一个字符(否定) [a-zA-Z] 从a到z或A到Z当中的任意一个字符(范围) [abc[hij]] a,b,c,h,i,j中的任意一个字符(与a|b|c|h|i|j相同)(并集) [a-z&&[hij]] h,i,j中的一个(交集) s 空格字符(空格键, tab, 换行, 换页, 回车) S 非空格字符([^s]) d 一个数字,也就是[0-9] D 一个非数字的字符,也就是[^0-9] w 一个单词字符(word character),即[a-zA-Z_0-9] W 一个非单词的字符,[^w]

如果你用过其它语言的正则表达式,那么你一眼就能看出反斜杠的与众不同。在其它语言里,”\”的意思是”我只是要在正则表达式里插入一个反斜杠。没什么特别的意思。”但是在Java里,”\”的意思是”我要插入一个正则表达式的反斜杠,所以跟在它后面的那个字符的意思就变了。”举例来说,如果你想表示一个或更多的”单词字符”,那么这个正则表达式就应该是”\w+”。如果你要插入一个反斜杠,那就得用”\\”。不过像换行,跳格之类的还是只用一根反斜杠:”
“。

这里只给你讲一个例子;你应该JDK文档的java.util.regex.Pattern加到收藏夹里,这样就能很容易地找到各种正则表达式的模式了。

逻辑运算符 XY X 后面跟着 Y X|Y X或Y (X) 一个”要匹配的组(capturing group)”. 以后可以用i来表示第i个被匹配的组。 边界匹配符 ^ 一行的开始 $ 一行的结尾  一个单词的边界 B 一个非单词的边界 G 前一个匹配的结束

举一个具体一些的例子。下面这些正则表达式都是合法的,而且都能匹配”Rudolph”:

Rudolph
[rR]udolph
[rR][aeiou][a-z]ol.*
R.*

数量表示符

“数量表示符(quantifier)”的作用是定义模式应该匹配多少个字符。

  • Greedy(贪婪的): 除非另有表示,否则数量表示符都是greedy的。Greedy的表达式会一直匹配下去,直到匹配不下去为止。(如果你发现表达式匹配的结果与预期的不符),很有可能是因为,你以为表达式会只匹配前面几个字符,而实际上它是greedy的,因此会一直匹配下去。
  • Reluctant(勉强的): 用问号表示,它会匹配最少的字符。也称为lazy, minimal matching, non-greedy, 或ungreedy。
  • Possessive(占有的): 目前只有Java支持(其它语言都不支持)。它更加先进,所以你可能还不太会用。用正则表达式匹配字符串的时候会产生很多中间状态,(一般的匹配引擎会保存这种中间状态,)这样匹配失败的时候就能原路返回了。占有型的表达式不保存这种中间状态,因此也就不会回头重来了。它能防止正则表达式的失控,同时也能提高运行的效率。

Greedy Reluctant Possessive 匹配 X? X?? X?+ 匹配一个或零个X X* X*? X*+ 匹配零或多个X X+ X+? X++ 匹配一个或多个X X{n} X{n}? X{n}+ 匹配正好n个X X{n,} X{n,}? X{n,}+ 匹配至少n个X X{n,m} X{n,m}? X{n,m}+ 匹配至少n个,至多m个X

再提醒一下,要想让表达式照你的意思去运行,你应该用括号把’X'括起来。比方说:

abc+

似乎这个表达式能匹配一个或若干个’abc’,但是如果你真的用它去匹配’abcabcabc’的话,实际上只会找到三个字符。因为这个表达式的意思是’ab’后边跟着一个或多个’c'。要想匹配一个或多个完整的’abc’,你应该这样:

(abc)+

正则表达式能轻而易举地把你给耍了;这是一种建立在Java之上的新语言。

CharSequence

JDK 1.4定义了一个新的接口,叫CharSequence。它提供了String和StringBuffer这两个类的字符序列的抽象:

interface CharSequence {
charAt(int i);
length();
subSequence(int start, int end);
toString();
}

为了实现这个新的CharSequence接口,String,StringBuffer以及CharBuffer都作了修改。很多正则表达式的操作都要拿CharSequence作参数。

Pattern和Matcher

先给一个例子。下面这段程序可以测试正则表达式是否匹配字符串。第一个参数是要匹配的字符串,后面是正则表达式。正则表达式可以有多个。在Unix/Linux环境下,命令行下的正则表达式还必须用引号。

当你创建正则表达式时,可以用这个程序来判断它是不是会按照你的要求工作。

//: c12:TestRegularExpression.java
// Allows you to easly try out regular expressions.
// {Args: abcabcabcdefabc “abc+” “(abc)+” “(abc){2,}” }
import java.util.regex.*;
public class TestRegularExpression {
public static void main(String[] args) {
if(args.length < 2) {
System.out.println(“Usage:
” +
“java TestRegularExpression ” +
“characterSequence regularExpression+”);
System.exit(0);
}
System.out.println(“Input: “” + args[0] + “”");
for(int i = 1; i < args.length; i++) {
System.out.println(
“Regular expression: “” + args[i] + “”");
Pattern p = Pattern.compile(args[i]);
Matcher m = p.matcher(args[0]);
while(m.find()) {
System.out.println(“Match “” + m.group() +
“” at positions ” +
m.start() + “-” + (m.end() – 1));
}
}
}
} ///:~

Java的正则表达式是由java.util.regex的Pattern和Matcher类实现的。Pattern对象表示