学习正则表达式:Pattern类

本文详细介绍Java中正则表达式的使用方法,包括Pattern、Matcher类的应用及常见元字符解析,通过实例展示如何匹配特定模式的文本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 正则表达式在处理文本方面用处非常大,最早像在Perl和awk语言中,提供了这种机制,Java在Java 2中也增加了正则表达式这个包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 = Pattern.compile(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 = Pattern.compile(regex);

然后调用Pattern的方法matcher Matcher 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 =Pattern.compile("A #matches uppercase US-ASCII char code 65",Pattern.COMMENTS);


MULTILINE:表明要输入多行,他们有自己的终止字符。 

Pattern p = Pattern.compile("^.", 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 = Pattern.compile("^.", Pattern.MULTILINE); //Pattern p = Pattern.compile(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 = Pattern.compile(".", Pattern.DOTALL);


如果我们输入的是Test\n,则匹配的字符是5个。

我们可以组合以上选项,只要使用|,进行按位或操作即可

Pattern p =   Pattern.compile("t # a compound flag example",Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE|Pattern.COMMENT);


我们还要注意点的是Java对转译字符\的处理,例如我们要匹配一个数字: 
我们不能使用: 

Pattern p = Pattern.compile("\d");


而是: 

Pattern p = Pattern.compile("\\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 =( Pattern.COMMENTS == (Pattern.COMMENTS & flgs)) ;



看看一个简化过程的方法: 

public static boolean matches (String regex,CharSequence input)



这个方法实际上是: 

Pattern p = Pattern.compile(regex);

Matcher m = p.matcher(candidate);

m.matches()


过程的一个简化,我们在后面总结Matcher中的matches方法之后就会理解这个了。

想必我们经常使用把字符串提取出token变成字符串数组的String中的split方法吧,下面我们看看 类似的一个方法: 
public String[] split(CharSequence input) 

这个方法提供了强大的功能,因为它可以使用正则表达式来作为token的分割: 

Pattern p = new Pattern.compile(",|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 = Pattern.compile(","); String temp[] = p.split("Hello,Dolly,", -1); //temp[]={"Hello","Dolly",""}




 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值