正则表达式在java程序中的应用分析[转的]

在正则表达式的规则中,'\'作为一个转义字符出现.由于在正则表达中,许多字符已经被作为正则表达式的关键字而被赋予了特殊的含义从而失去了它们本身的含义.例如'*'在正则表达式中表示匹配'*'前面的子表达式零次或多次,假如想匹配一个正常的'*'字符,就要使用'\*'来表示.而在Java源代码的字符串中,'\'首先被被Java字节码编译器解释java语言中定义的Unicode转义或其他字符转义,所以想在java源代码中表示正则表达式中一个正常的'*'字符,需要加两个'\',即'\\*',表示把第二个'\'转成java源代码中一个正常的字符,而这个正常的字符则在这段java源码中的正则表达式中表示正则表达式中的转义字符.
    如果要表示java源码中的正则表达式的一个正常的'\'字符,则需要这样表示'\\\\',其中第一第三个'\'均表示java编译器中的转义字符第二个则表示正则表达式中的转义字符,从而把第四个'\'转义为正则表达式中一个普通的'\'字符.

    1,匹配判断与查找
    在java中,匹配判断操作常用的类有两个:java.util.regex.Pattern,java.util.regex.Matcher.
    Pattern是字符串形式的正则表达式的编译类,指定为字符串的正则表达式必须首先被编译为它的实例.
    Matcher被定义为"通过解释 Pattern 对 字符序列 执行匹配操作的引擎".
    通俗一些说,一个字符形式的正则表达式编译成为一个Pattern的实例,相当于扫雷中的一个扫雷器,而Pattern的实例的matcher方法(参数相当于某一个地点)则相当于拿这个扫雷器的人,当执行Matcher的实例方法matches()后,此方法返回一个表示是否匹配的boolean值,而这个操作就相当于这个人把这个扫雷器放到这个地点后,这个人看到扫雷器上面的指示,就会得出这个地方是否有雷的信息.
    假如我们想判断一个文件名中是否包含.class这个后缀名,由于.class后缀名有时候会有大小写的不同形式,那么可以使用以下方式判断:
    1>首先构造正则表达式
    //此正则表达式表示,在.class中的.号前面紧挨着的字符不能是空字符,必须是其它字符,或者是.class后面不再有其它字符,或者是","或空字符,或二者之后再跟其它字符串,"."表示匹配任意字符,[^]表示除紧跟在它之后字符的其它任意字符,+表示匹配至少1次,*表示匹配至少0次,{0,1}表示匹配0或1次,[cC]表示匹配大写或小写c等价于[c|],"|"表示或的运算,()内表示一个完整的字符串表达式
   String regex = ".*[^ ]+\\.[cC][lL][aA][sS][sS]([,| ].*){0,1}";
   Pattern p = Pattern.compile( regex );
   Matcher m = p.matcher( " file1.class,test.txt" )
   boolean b = m.matches();
   这个正则表达式可以匹配" xx.class,"或"xx.class "或"xx.class"或"xx.clss,xxx"或"xx.class xxx"等诸多形式字符串.

   另外一对有用的定位符是"^"和"$",在和"+"和"*"等这些限定符结合使用时,可以匹配某些特殊的字符串,如每章的章节
   //B表示一行的中间位置,^表示行的开头,$表示行的结尾
   String regex = "^ *第http://www.cnblogs.com/gardenforu/admin/file://b[1-9]%7b1%7d//d*章 +[^ ]+.*[^ ]* *$";
   Pattern p = Pattern.compile( regex );
   Matcher m = p.matcher( " 第1章 南 昌 起 义 " );
   boolean b = m.matches();
   这个表达式可以匹配" 第1章 南昌起义 "或"第1章 南昌起义"等样式的章节名,它的限制有,行的开头除空格外只允许出现"第"字,并且"第"字给紧跟一个非0的整数,数字后面则必须紧跟"章"字,并且"第x章"后面紧跟一个或多个空格,然后空格后必须有非空的章节名.章节名中间以及章节名后至行结尾允许有空字符,但章节名必须包含至少一个非空字符,其它的占位符及限定符用法请参考相关文档.

   另外,Pattern预定义了一些常量表示常用的匹配模式,如CASE_INSENSITIVE表示匹配时不区分大小写,可使用另一个compile方法:
   String regex = "http://www.cnblogs.com/gardenforu/admin/file://.class/";
   Pattern p = Pattern.compile( regex, Pattern.CASE_INSENSITIVE );
   Matcher m = p.matcher( ".Class" );
   boolean b = m.matches();//b的值为true

   类Pattern的实例一旦编译,就不能再改变,是线程安全的,所以可以用在并发操作中.
   对于只使用一次的模式,可以考虑使用Pattern的静态方法matches( String regex, CharSequence input ),在仅使用一次正则表达式时,可以方便地通过此类定义matches方法.此方法编译表达式并在单个调用中将输入序列与其匹配.语句
   boolean b = Pattern.matches("a*b", "aaaaab");
   等效于上面的三个语句.
   但是对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式.
  
   还有一种匹配判断的验证方法,就是使用String的matches(String regex)方法.
   String s = ".Class";
   boolean = s.matches(http://www.cnblogs.com/gardenforu/admin/file://.[cc][ll][aa][ss][ss/])

   2.String对象中的字符串替换与分割
   在String的方法中,有两个替换方法和两个分割方法可以使用正则表达式
   1> replaceAll(String regex, String replacement)"使用给定的replacement字符串替换此字符串匹配给定的正则表达式的所有子字符串
   2> String replaceFirst(String regex, String replacement):使用给定的replacement字符串替换此字符串匹配给定的正则表达式的第一个子字符串
   3> String[] split(String regex):根据给定的正则表达式的匹配来拆分此字符串。
   4> String[] split(String regex, int limit)根据匹配给定的正则表达式来拆分此字符串,后面一个参数决定返回的字符数组的长度

   这几个方法在使用正则表达式时,对于正则表达式的构造方法是一样的,如给定模式"http://www.cnblogs.com/gardenforu/admin/file://.[cc][ll][ss][ss/]",替换字符串为.class,前三个方法依次这样执行:替换给定字符串中所有含有不区分大小写的.class字母,替换第一个,以不区分大小写的.class分割字符串.

   split(String regex, int limit)这个方法在使用的时候有点特别,因为多了一个匹配次数的限制参数.
   文档解释如下
   limit参数控制模式应用的次数,因此影响结果数组的长度.如果该限制n大于0,则模式将被最多应用n-1次,数组的长度将不会大于n,而且数组的最后项将包含超出最后匹配的定界符的所有输入.如果n为非正,则模式将被应用尽可能多的次数,而且数组可以是任意长度.如果n为零,则模式将被应用尽可能多的次数,数组可有任何长度,并且结尾空字符串将被丢弃.
   例如
   "TestaTestATestaTest".split("a|A",2);//则分割出来的字符串为Test,TestATestaTest
   "TestaTestATestaTest".split("a|A",3);//则分割出来的字符串为Test,Test,TestaTest

   另外,这个方法同Pattern的split方法的效果一样
   Pattern.compile( "a|A" ).split( "TestaTestATestaTest", 2 );

   有时候,匹配某些文本编辑器或数据库中的文本内容中的换行符需要使用\n|\r\n

posted on 2009-09-24 17:14    阅读(337)  评论(0编辑  收藏  举报

导航