当前位置:文档之家› 正则表达式的学习资料

正则表达式的学习资料

正则表达式在处理文本方面用处非常大,最早像在Perl和awk语言中,提供了这种机制,Java在Java2中也增加了正则表达式这个包java.util.regex。

这个包为用户使用正则表达式,提供了易用而全面的支持。

我的研究方向是web挖掘。

从网页中提取内容,处理文本,当然需要正则表达式这个强大的工具了。

一、首先我们看一下怎么使用正则表达式的一个例子:A Matcher examines the results of applying a pattern.我们希望从这句话中找到所有开头为a的单词。

当然这只是一个简单的例子,你可以使用String提供的split方法,得到单词数组,然后遍历各个单词看是否是否开头为a我们现在看看怎么使用正则表达式来处理这个问题:import java.util.regex.*;public class FindA{public static void main(String args[])throws Exception{String candidate="A Matcher examines the results of applying a pattern.";String regex="\\ba\\w*\\b";Pattern p=pile(regex);Matcher m=p.matcher(candidate);String val=null;System.out.println("INPUT:"+candidate);System.out.println("REGEX:"+regex+"\r\n");while(m.find()){val=m.group();System.out.println("MATCH:"+val);}if(val==null){System.out.println("NO MATCHES:");}}}从这个例子我们可以看到正则表达式涉及到的两个类Matcher和Pattern,我们以后会专门讨论着连个类。

现在主要看看使用正则表达式的流程:首先使用Pattern的一个静态的方法compile来创建Pattern对象,Pattern p=pile(regex);然后调用Pattern的方法matcherMatcher m=p.matcher(candidate);得到了Matcher对象,Matcher对象保存了许多匹配信息,然后可以通过find()方法查找匹配的部分,如果有匹配的部分,返回真,使用m.group方法得到匹配的各组值,否则find返回false.当然这只是一般的过程,还有许多更细的方法,在以后会陆续的总结,下面我们看一下String regex="\\ba\\w*\\b";这个就是一个正则表达式,b,w,*都是正则表达式的meta character原字符,\b表示单词的边界,w表示任意的可构成单词的字母数字,*表示前面的字母(当然可以是更复杂的组之类的了东东)重复0次或0次以上,a当然还是a了。

所以这个regex就匹配单词开头为a的单词了。

二、下面总结一下基本的正则表达式的meta character以及它们含义:.匹配任意一个字符$匹配一行的结尾^匹配一行的开头(在[]里面表示否定){}定义了一个范围[]定义了一个字符类()定义了一个组*前面出现0次以上+前面匹配一次以上?前面出现0次或一次\后面的字符不会看作metacharacter\w字母数字下划线\W非字母数字下划线\d单个数字\D单个非数字|或,二者之一&&与操作符\b单词边界下面看看几个简单的例子:[abc]a、b或c(简单类)[^abc]任何字符,除了a、b或c(否定)[a-zA-Z]a到z或A到Z,两头的字母包括在内(范围)[a-d[m-p]]a到d或m到p:[a-dm-p](并集)[a-z&&[def]]d、e或f(交集)[a-z&&[^bc]]a到z,除了b和c:[ad-z](减去)[a-z&&[^m-p]]a到z,而非m到p:[a-lq-z](减去)三、java.util.regex提供的操作接口:java.util.regex包提供了操作正则表达式的模型,整个模型优雅而简洁,只有三个类:Pattern、Matcher和PatternSyntaxException。

下面将要总结他们提供的方法,以及如何灵活应用来处理文本。

我们还是从Pattern的静态工厂方法来扩展吧:static Pattern compile(String regex)???将给定的正则表达式编译到模式中,并创建Pattern对象,这个方法通常是操作正则表达式的第一步,从前面那个例子我们也可以看到整个的流程。

在看看一个重载的compile方法:static Pattern compile(String regex,int flags)将给定的正则表达式编译到具有给定标志的模式中。

这个方法参数flags提供了一些特殊的选项来用于特殊的处理,我们下面看看可使用的选项:UNIX_LINES:这个主要处理UNIX和其他的操作系统在行结束符不一样的问题,UNIX使用\n代表一行的终止,而Windows则使用了\r\n,\n,\r,\u2028或者\u0085作为一行的结束符。

CASE_INSENSITIVE:当我们在匹配的时候要忽略字符大小写时COMMENTS:允许我们在正则表达式中使用注释,例如Pattern p=pile("A#matches uppercase US-ASCII char code 65",MENTS);MULTILINE:表明要输入多行,他们有自己的终止字符。

Pattern p=pile("^.",Pattern.MULTILINE);如果你的输入的字符串是:This is a sentence.\nSo is this..这样我们匹配的字符是This中的T和So中的S,如果不使用MULTILINE,则只会匹配T程序:import java.util.regex.*;public class Multiline{public static void main(String args[])throws Exception{String candidate="This is a sentence.\nSo is this..";String regex="^.";Pattern p=pile("^.",Pattern.MULTILINE);//Pattern p=pile(regex,Pattern.MULTILINE);Matcher m=p.matcher(candidate);String val=null;System.out.println("INPUT:"+candidate);System.out.println("REGEX:"+regex+"\r\n");while(m.find()){val=m.group();System.out.println("MATCH:"+val);}if(val==null){System.out.println("NO MATCHES:");}}}DOTALL:使用这个选项之后metacharacter.就可以包括一行的终止字符了,如果没有这个选项,一行的终止字符,并不会考虑在字符串之内的。

使用这个选项会降低效率Pattern p=pile(".",Pattern.DOTALL);如果我们输入的是Test\n,则匹配的字符是5个。

我们可以组合以上选项,只要使用|,进行按位或操作即可Pattern p=pile("t#a compound flagexample",Pattern.CASE_INSENSITIVE|Pattern.UNICODE_CASE|MENT);我们还要注意点的是Java对转译字符\的处理,例如我们要匹配一个数字:我们不能使用:Pattern p=pile("\d");而是:Pattern p=pile("\\d");另外如果regex本身形式是错误的,compile方法会抛出java.util.regex.PatternSyntaxException异常。

下面我们总结一下public Matcher matcher(CharSequence input)方法:当我们使用compile操作,创建了Pattern对象之后,我们就可以使用Pattern对象的matcher操作,生成matcher 对象了,Matcher对象包含了许多对匹配结果集的操作,我们在总结Matcher对象的时候再说。

另外顺便提一下参数CharSequence,CharBuffer,Segment,String,StringBuffer,StringBuilder都实现这个接口,所以参数可以是这些中的任一种类型了。

下面我们看看:public int flags()这个方法返回了我们前面可以设置的并且已经设置的flags选项,我们通过按位与来判断是否设置了某个选项:int flgs=myPattern.flags();boolean isUsingCommentFlag=(MENTS==(MENTS& flgs));看看一个简化过程的方法:public static boolean matches(String regex,CharSequence input)这个方法实际上是:Pattern p=pile(regex);Matcher m=p.matcher(candidate);m.matches()过程的一个简化,我们在后面总结Matcher中的matches方法之后就会理解这个了。

想必我们经常使用把字符串提取出token变成字符串数组的String中的split方法吧,下面我们看看类似的一个方法:public String[]split(CharSequence input)这个方法提供了强大的功能,因为它可以使用正则表达式来作为token的分割:Pattern p=new pile(",|and");String fruits[]=p.split("apple,banana and orange");split的一个重载的版本:public String[]split(CharSequence input,int limit)它指定了划分的组数,有以下三种情况:limit==0这时候和没有limit参数的那个split效果一样limit>0如果你仅仅对前limit个感兴趣,你可以使用limit:String[]tmp=pattern.split("Hello,Dolly,You,Are,My,Favorite",3); //tmp[0]is"Hello",//tmp[1]is"Dolly";//tmp[2]is"You,Are,My,Favorite";limit<0会尽可能的划分所有的组,即使分割符后面是个空字符,也要单独生成一个token:""Pattern p=pile(",");String temp[]=p.split("Hello,Dolly,",-1);//temp[]={"Hello","Dolly",""}。

相关主题