正则表达式正则表达式是JDK 1.4的新功能,但是对sed和awk这样的Unix的标准实用工具,以及Python,Perl之类的语言来讲,它早就已经成为其不可或缺的组成部分了(有人甚至认为,它还是Perl能大获成功的最主要的原因)。
单从技术角度来讲,正则表达式只是一种处理字符串的工具(过去Java这个任务是交由String,StringBuffer以及StringTokenizer处理的),但是它常常和I/O一起使用,所以放到这里来讲也不算太离题吧。
正则表达式是一种功能强大但又非常灵活的文本处理工具。
它能让你用编程的方式来描述复杂的文本模式,然后在字符串里把它找出来。
一旦你找到了这种模式,你就能随心所欲地处理这些文本了。
虽然初看起来正则表达式的语法有点让人望而生畏,但它提供了一种精练的动态语言,使我们能用一种通用的方式来解决各种字符串的问题,包括匹配,选择,编辑以及校验。
创建正则表达式你可以从比较简单的东西入手学习正则表达式。
要想全面地掌握怎样构建正则表达式,可以去看JDK 文档的java.util.regex的Pattern类的文档。
正则表达式的强大体现在它能定义字符集(character class)。
下面是一些最常见的字符集及其定义的方式,此外还有一些预定义的字符集:如果你用过其它语言的正则表达式,那么你一眼就能看出反斜杠的与众不同。
在其它语言里,"\"的意思是:“只是要在正则表达式里插入一个反斜杠。
没什么特别的意思。
”但是在Java里,"\"的意思是:“要插入一个正则表达式的反斜杠,所以跟在它后面的那个字符的意思就变了。
”举例来说,如果你想表示一个或更多的"单词字符",那么这个正则表达式就应该是"\w+"。
如果你要插入一个反斜杠,那就得用"\\"。
不过像换行,跳格之类的还是只用一根反斜杠:"\n\t"。
这里只给你讲一个例子;你应该JDK文档的java.util.regex.Pattern加到收藏夹里,这样就能很容易地找到各种正则表达式的模式了。
举一个具体一些的例子。
下面这些正则表达式都是合法的,而且都能匹配"Rudolph":Rudolph[rR]udolph[rR][aeiou][a-z]ol.*R.*数量表示符数量表示符(quantifier)的作用是定义模式应该匹配多少个字符。
∙Greedy(贪婪的):除非另有表示,否则数量表示符都是greedy的。
Greedy的表达式会一直匹配下去,直到匹配不下去为止。
(如果你发现表达式匹配的结果与预期的不符),很有可能是因为,你以为表达式会只匹配前面几个字符,而实际上它是greedy的,因此会一直匹配下去。
∙Reluctant(勉强的):用问号表示,它会匹配最少的字符。
也称为lazy, minimal matching, non-greedy, 或ungreedy。
Possessive(占有的):目前只有Java支持(其它语言都不支持)。
它更加先进,所以你可能还不太会用。
用正则表达式匹配字符串的时候会产生很多中间状态,(一般的匹配引擎会保存这种中间状态,)这样匹配失败的时候就能原路返回了。
占有型的表达式不保存这种中间状态,因此也就不会回头重来了。
它能防止正则表达式的失控,同时也能提高运行的效率。
再提醒一下,要想让表达式照你的意思去运行,你应该用括号把'X'括起来。
比方说:abc+似乎这个表达式能匹配一个或若干个'abc',但是如果你真的用它去匹配'abcabcabc'的话,实际上只会找到三个字符。
因为这个表达式的意思是'ab'后边跟着一个或多个'c'。
要想匹配一个或多个完整的'abc',你应该这样:(abc)+正则表达式能轻而易举地把你给耍了;这是一种建立在Java之上的新语言。
CharSequenceJDK 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:\n" +"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 = pile(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对象表示经编译的正则表达式。
静态的compile( )方法负责将表示正则表达式的字符串编译成Pattern对象。
正如上述例程所示的,只要给Pattern的matcher( )方法送一个字符串就能获取一个Matcher对象。
此外,Pattern还有一个能快速判断能否在input里面找到regex的(注意,原文有误,漏了方法名)static boolean matches( regex, input)以及能返回String数组的split( )方法,它能用regex把字符串分割开来。
只要给Pattern.matcher( )方法传一个字符串就能获得Matcher对象了。
接下来就能用Matcher的方法来查询匹配的结果了。
boolean matches()boolean lookingAt()boolean find()boolean find(int start)matches( )的前提是Pattern匹配整个字符串,而lookingAt( )的意思是Pattern匹配字符串的开头。
find( )的功能是发现CharSequence里的,与pattern相匹配的多个字符序列。
例如://: c12:FindDemo.javaimport java.util.regex.*;import com.bruceeckel.simpletest.*;import java.util.*;public class FindDemo {private static Test monitor = new Test();public static void main(String[] args) {Matcher m = pile("\\w+").matcher("Evening is full of the linnet's wings");while(m.find())System.out.println(m.group());int i = 0;while(m.find(i)) {System.out.print(m.group() + " ");i++;}monitor.expect(new String[] {"Evening","is","full","of","the","linnet","s","wings","Evening vening ening ning ing ng g is is s full " +"full ull ll l of of f the the he e linnet linnet " +"innet nnet net et t s s wings wings ings ngs gs s "});}} ///:~"\\w+"的意思是"一个或多个单词字符",因此它会将字符串直接分解成单词。
find( )像一个迭代器,从头到尾扫描一遍字符串。
第二个find( )是带int参数的,正如你所看到的,它会告诉方法从哪里开始找——即从参数位置开始查找。