Java的正则表达式试用

     Java的正则表达式对于字符串的模式匹配很有好处,用起来似乎很方便。不过,由于JDK的帮助中只是简单地罗列了正则表达式的构造摘要,其写法对于正确地理解证则表达式不太直观。今天,抽时间对于正则表达式进行了试用,获得了如下收获:
关于正则表达式的意义和相关类
    正则表达式的使用是基于“模式”的概念的,即以表达式规定的语法来描述在字符串匹配时的模式。当具体字符串与表达式表达的模式符合时,则匹配结果为真,否则为假。这样,我们可以通过表达式来描述比较复杂的字符串匹配模式,从而方便地完成字符串的有关操作。
    为了实现上述目的,JDK构造了两个最终的类:模式类Pattern和匹配器类Matcher,这两个类都包含在包java.util.regex中。如果需要使用,可以包含这个包。
    模式类用来构造匹配模式。一个生成的模式可以用于多个匹配器。模式的产生是通过调用其compile方法完成的,而匹配器使用的匹配模式及将模式应用于匹配具体字符串是通过引用具体模式的matcher方法完成的,典型的用法如下:
    Pattern p=Pattern.compile("a*b");  //声明匹配器p并编译其模式为a*b
    Matcher m=p.matcher("aaaaaabcd");//声明匹配器m并应用匹配模式p,输入匹配字符串aaaaaaabcd
    这样,当匹配器创建好后,就可以利用它的有关方法进行各种匹配操作,如matches,find,group等,而匹配结果则存储在匹配器中。具体方法的意义在JDK帮助中有相关的叙述。
   当然,如果对于特定的字符串只使用特定的匹配模式一次,可以简单地用一个语句来写,如:
    boolean b=Pattern.matches("a*b","aaaaabcd");
    在这里,要用好这种匹配,其实最关键的是构造好正则表达式,用来表达恰当的模式。
    至于在实际的使用中,由于String中的相关方法可以直接使用正则表达式,所以上述对于模式类和匹配器类的使用往往都可以省略,甚至连包都可以不用包含。例如,下面的例子利用正则表达式删除了满足模式的子字符串:
    s.replaceAll("a//d*b","");
关于正则表达式
    如何构造正确的正则表达式,来满足自己的需求是非常关键的。正则表达式通常由普通字符,字符类(字符集),通配符,量词等组成。下面是它的主要要点:
    正则表达式由字符串构成,即正则表达式字符串中按照其语法来描述相应模式。
    普通字符表示了模式中该字符本身。例如,正则表达式“e”代表了匹配字符串中的所有字符e,而正则表达式“phone”则代表了匹配字符串的所有字符串phone。
    字符类是字符的集合,该集合包含在防括弧[ ]中,例如[xyz]。字符类由于是集合,和普通字符不同,匹配时表现为或的关系,如前例表示字符x、y或者z都是满足该模式的。同时,可以利用^号来对字符类进行反向运算,即[^xyz]表示除字符x、y和z以外的所有字符。但是应该注意的是,^的反向运算只对字符类有用,在普通字符中,它的意义是行的开头,所以,“^x"并不是除x以外的其它字符,只有[^x]才是这个意思。还可以利用-进行范围指定,如[0-9]表示所有的数字字符。
    与转义字符类似,正则表达式中的/也具有相同的意思,如/n表示换行符,/t表示制表符,//表示/本身。不过要注意的是,由于正则表达式是字符串,字符串本身也需要转义字符,所以写正则表达式时对于所有转义字符其实都必须写成//的形式,如“/n”不会被解释为换行符,而“//n”才是这个意思。
    正则表达式还预定义了一些字符以方便使用,如/d表示数字字符,即[0-9];/D表示非数字字符,即[^0-9]等等。
    量词表示一个模式重复的次数,常用的量词如下:
    ?:表示0次或者1次
    *:表示0次或者多次
    +:表示1次或者多次
    有了量词,可以表示很多灵活的意义,如可以用/d+表示所有的数字字符串等等。
    其它的量词意义可以参见JDK帮助。
关于正则表达式的使用
    使用正则表达式时,应该根据语法仔细分析,才能够获得希望的结果。如下例所示:
public   class  test  {
    
public static void main (String arg[]) {
        String s
="It is a number -10.23 | .34 | -45 | 56";
        System.out.println(s.replaceAll(
"//-?//d*//.?//d+","/"));
        System.out.println(s.replaceAll(
"[//-?//d*//.?//d+]","/"));
        System.out.println(s.replaceAll(
"[^//-?//d*//.?//d+]","/"));
    }

}
    这里,采用字符串的replaceAll方法来考察正则表达式的效果。该函数替换字符串中满足正则表达式模式的所有子字符串。我们用/来进行替换,以显示替换效果。
    首先分析正则表达式"//-?//d*//.?//d+",其意义其实是所有正负实数串或整数串。为了表达这样的意义,首先我们应该分析这样的串的特征。正整数串是最好表达的,用“//d+”即可。但如果需要表达正负,则有可能有负号,这时,可以采用“//-//d+"来表达负整数,但由于同时也需要表达整数,则必须表示出-号可有,可以没有,并且有也只能有一个的意思,所以,需要用量词?,即”//-?//d+“来表达。进一步,如果需要表达实数,则必须考虑小数点。但实数的写法可能有-10.23,.34,0.57这些写法,仔细分析,即对于小数点.可能有一个或者没有,而在小数点前或者后的数字,则可能没有,有一个,或者多个,因此,“//-?//d*//.?//d+”可以表示这个意义,但不能写成”//-?//d+//.?//d*"或者“//-?//d*//.?//d*"。前者对于.34这样的写法,由于小数点前没有数字,所以替换结果会去除不了小数点。而后一种写法,其实对所有长度为零的字符(没有字符)都满足,会每个字符后面都产生一个替换,所以都是不合适的。
    以普通字符的形式写上述实数意义的正则表达式,则在进行匹配时对于每一个实数整体只产生一次替换,即第一句地换的结果为“It is a number / | / | / | /“。但以[ ]包括的字符类的形式写这样的表达式,由于式中的字符间的关系为或,则每一个满足的字符都会替换一次,即对每一个负号、小数点和数字字符都会产生一次替换,所以第二句的替换结果为”It is a number // | /// | /// | //“。而第三句中,在字符类中用^进行了反运算,其意义实际为替换所有非数字字符串。从理论上讲,第三句的写法替换会对所有的非数字字符进行,即运行结果为”///-10.23///.34///-45///56“,这与理想的替换效果有差别,但由于反向运算只能对数字类进行,所以也是没有办法的事情。
    下面的例子从一个包含纯数字串,纯字符串,数字、字符混合串的单词字符串提取出纯粹的字符单词和数字单词:
public   class  Cbase  {
    
public static void main(String[] arg){
        String s
="strA strB 01 02 c10 11c 12c12 20num num21 num22num";
        String num
=s.replaceAll("//b//d*[a-zA-Z]+//d*[a-zA-A]*//b""");
        System.out.println(
"Just number: "+num);
        String str
=s.replaceAll("//b[a-zA-Z]*//d+[a-zA-Z]*//d*//b""");
        System.out.println(
"Just string: "+str);
    }

}
    其运行结果如下:
Just number:   01 02     
Just string: strA strB       
    第一个正则表达式 "//b//d*[a-zA-Z]+//d*[a-zA-A]*//b"匹配了纯粹的字母单词和混合有数字的字母单词,从而提取出了非纯数字单词。其语法分析是这样的:作为单词,首先必须有单词边界符/b在单词的首尾来包含整个表达式。其次,必须包含至少一个字母字符的单词,所以有[a-zA-Z]+。在字母字符的前边、后边都可能有0个或者多个数字字符,所以有//d*[a-zA-Z]+//d*。同时,还应该匹配数字混在字母字符中间的情况,所以,利用[a-zA-A]+//d*[a-zA-Z]*或者[a-zA-Z]*//d*[a-zA-Z]+来匹配。综合上述情况,最后获得了非纯数字单词的模式。不过,该模式依旧不能匹配混有多个数字的非纯字母单词,这是因为按照这个写法,必须知道混杂的数字字符的位置和次数,要写出一个通用的模式我还没有找到好的方法。
    第二个正则表达式思路和第一个是相似的,只是匹配了非纯字母单词。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值