JAVA基础笔记之正则表达式

来源:互联网 发布:梦里花落知多少演员表 编辑:程序博客网 时间:2024/05/21 20:23

1.什么是正则表达式
  正则表达式是一种用于定义字符串模式的特殊语言,这种被定义的字符串可以用来完成对目标字符串的匹配、搜索、替换等工作。

2.Java中使用正则表达式

  用户如果想在java中使用正则表达式,最方便的方法是加载jre中自带的类库java.util.regex。 java.util.regex包括以下3个类:
  1)Pattern类:Pattern类实例化对象为一个正则表达式,它本身没有公共的构造函数,需要调用一个静态方法compile来完成Pattern的实例化。
  2)Matcher类:Matcher类可以对输入的字符串进行解释和匹配的操作。和Pattern类一样,Matcher类本身没有公共的构造函数。和Pattern类不同的是,Matcher类必须通过Pattern类的方法matcher来完成实例化。
  3)PatternSyntaxException类:这是一个非强制异常类,他表示正则表达式中的语法错误

以下是regex包的一个应用例子:

   String str = "foodogfoo"; //带匹配的字符串   String regex = "foo"; //正则表达式   Pattern pattern = Pattern.compile(regex);      Matcher matcher = pattern.matcher(str);      while (matcher.find()) {          System.out.printf("I found the text \"%s\" starting at index %d "+"and ending at index %d.%n",  matcher.group(), matcher.start(), matcher.end());         }   

输出:

I found the text “foo” starting at index 0 and ending at index 3.
I found the text “foo” starting at index 6 and ending at index 9.

3.元字符
 正则表达式中有一些特殊的符号,如.[]/()?*+等,这些符号在解析表达式时会用来表示特性的含义,而不会被当做一般的字符。
 比如,元字符”.“在正则表达式中会被认为表示任意字符,”ab.“ 可以匹配 ”abc“、”abd“、”ab1“等。其他转义符的作用,笔者后文会写到。
 另外,在一些情况下,我们必须把元字符当做一般字符来使用,我们有两种办法来解决这个问题:
 1)在元字符前加”\“,这是元字符中的转义符。
 2)将需要转义的元字符放在”\Q“和”\E“之间。注意:”\Q“和”\E“可以放在字符串任意部分,但他们的顺序不能颠倒,”\Q“代表应用开始,”\E“代表引用结束。

4.字符类
  先摘抄一下常用的一些表达式
1)[abc]        匹配在abc三个字符中的任意一个
2)[^abc]       匹配abc外的任意字符
3)[a-d]        匹配a到d(abcd)四个字符中的任意一个
4)[a-dt-v]       匹配a到d以及t到v中的任意一个字符
5)[a-d[t-v]]      匹配a到d以及t到v中的任意一个字符(同上)
6)[a-d&&[t-v]]    匹配a到d以及t到v中的任意一个字符(同上)
7)[a-d&&[tuv]]    匹配a到d以及tuv中的任意一个字符
8)[r-w&&[^tuv]]   匹配r到w且是tuv之外的任意一个字符
9)[r-w&&[^t-v]]   匹配r到w且是t到v之外的任意一个字符

分别列举下字符类的例子
1)[abc]at:能够匹配aat、bat、cat
2)[^abc]at:不能匹配aat、bat、cat,但可以匹配dat、eat、3at、1at等
3)[a-d]at:能够匹配aat、bat、cat、dat
4)[a-dt-z]at或[a-d[t-z]]at、[a-d&&[t-z]]at、[a-d&&[tuv]]at:能够匹配aat、bat、cat、dat、tat、uat、vat
5)[o-w&&[^tuv]]at或[o-w&&[^t-v]]at:匹配rat、sat、wat

5.预定义字符类
pattern的api包中定义了许多有用的预定义字符类以代替相对应的字符,使用这些字符类可以让正则表达式有更好的可读性。
1). 任何字符(根据设定,可以匹配或不匹配结束符)
2)\d 数字字符 [0-9]
3)\D 非数字字符 [^0-9]
4)\s 空白字符 [\t\n\x0B\f\r]
5)\S费空白字符 [^\s]
6)\w 单词字符 [a-z[A-Z][0-9]]
7)\W 非单词字符[^a-z&&[^A-Z]&&[^0-9]]

由于在java语法中,”\“为转义符,如果直接使用”\d“等预定义字符类会造成编译器的错误理解,所以在编译阶段使用时需要在预定义字符类之前加上一个”\“,即”\d“。

分别列举下预定义字符类的例子:
1)foo\dfoo:匹配foo1foo,不能匹配fooafoo、foo&foo
2)foo\Dfoo:匹配fooafoo、foo&foo,不能匹配foo1foo
3)foo\sfoo:匹配foo foo
4)foo\Sfoo:不能匹配foo foo
5)foo\wfoo:匹配fooafoo、foozfoo、foo8foo,不能匹配foo foo、foo!foo
6)foo\Wfoo:不能匹配fooafoo、foozfoo、foo8foo,匹配foo foo、foo!foo

6.量词
  正则表达式中,可以使用量词来匹配某字符串重复出现的次数,而量词又分为贪婪(greedy)、勉强(reluctant)、侵占(possession)三种类型。
  
    量词种类              意义
 贪婪  勉强  侵占
 X?  X??  X?+        匹配X零次或一次
 X*  X*?  X*+        匹配X零次或多次
 X+  X+?  X++        匹配X一次或多次
 X{n} X{n}?  X{n}+        匹配Xn次
 X{n,} X{n,}? X{n,}+       匹配X至少n次
 X{n,m} X{n,m}? X{n,m}+    匹配X至少n次且至多m次

贪婪:编译器首先会读取整个被匹配的字符串,并尝试匹配;如果失败,则”吐出“最后一个字符,并再次尝试匹配;编译器会不断”吐出“最后一个字符并尝试匹配正则表达式,直到匹配成功或字符长度为0。
勉强:和贪婪相反,编译器不会预先读取整个字符串,而是从第一个字符开始匹配,逐渐读取字符串更多的字符,直到匹配成功或读取完整个字符串。
侵占:和贪婪一样,编译器首先会读取整个被匹配的字符串,并尝试匹配,但匹配失败后就结束匹配。

实例(匹配字符串xfooxxxxxxfoo ):
1).*foo :匹配成功,成功一次。
匹配过程:
i.编译器预先读取xfooxxxxxxfoo 字符串,.*消耗掉整个字符串,匹配失败;
ii.编译器不断”吐出“字符,直到还剩下字符串”xfoo“,匹配成功;
iii.编译器继续”吐出“字符直到最后一个,匹配结束。
2).*?foo:匹配成功,成功两次。
匹配过程:
匹配过程:
i.编译器预先读取x字符串,匹配失败;
ii.编译器不断读取字符,直到读取字符串”xfoo“,匹配成功;
ii.编译器继续不断读取字符,直到读取字符串”xfooxxxxxxfoo“,匹配成功;
iii.因为已经是最后一个字符,匹配结束。
3).*+foo:匹配失败。
匹配过程:
i.编译器预先读取xfooxxxxxxfoo 字符串,.*消耗掉整个字符串,匹配失败;
ii.侵占量词不会进行第二次匹配,匹配结束。

7.捕获组

  正则表达式中的子表达式可以被小括号括起来,作为一个相对独立的单元进行处理,这个被括起来的子表达式,就是一个捕获组。一个正则表达式可以有多个捕获组,这写捕获组可以互相嵌套,形成一个多层的捕获组,比如((A)(B(C)))。
  编译器会按按括号从左到右的方式分别为正则表达式中的捕获组安排一个编号,上例中捕获组的标号为
  1)(A(B(C)))
  2)(A)
  3)(B(C))
  4)(C)
  
  通过Matcher对象的方法,我们可以获得捕获组的相关信息:
  int groupCount()  返回捕获组数量
  int start(int group)  返回之前group组所捕获的初始索引
  int end(int group)  返回之前group组所捕获的最后索引+1
  string group(int group) 返回之前的匹配操作期间,通过给定组而捕获的输入子序列。
 
捕获组的反向引用
  编译器会将捕获组存入内存中,所以在编辑正则表达式时,可以从内存中调用已存入内存的捕获组,使用格式是”\“加上捕获组的编号,比如”\1“。
  表达式(\w\d)定义了两个字的捕获组,(\w\d)\1则等同于(\w\d){2}。
实例:
(\w\d)\1:能够匹配t1t1,而不能匹配t1t2或e1t1。

8.边界匹配器
  就目前而言,我们的兴趣在于指定输入字符串中某些位置是否有匹配,还没有考虑到字符串的匹配产生在什么地方。
  通过指定一些边界匹配器(boundary matchers)的信息,可以使模式匹配更为精确。比如说你对某个特定的单词感兴趣,并且它只出现在行首或者是行尾时。又或者你想知道匹配发生在单词边界(word boundary),或者是上一个匹配的尾部。
  下表中列出了所有的边界匹配器及其说明。
        ^     行首
        $     行尾
        \b    单词边界
        \B    非单词边界
        \A    输入的开头
        \G    上一个匹配的结尾
        \Z    输入的结尾,仅用于最后的结束符(如果有的话)
        \z     输入的结尾

0 0
原创粉丝点击