Java中使用正则

这应该是比较常用的吧….可惜我忘了,还有字符串相关的方法使用频率也很高
Java 提供了 java.util.regex 包来与正则表达式进行模式匹配。注意使用的就是两个类,Pattern Matcher 其他语言也挺类似的,使用方法也比较一致

对了字符串这个对象吧….其实是“固定的”(不可变),每次改变都会重新开辟内存,所以还是尽量少频繁的使用String+=…

java.util.regex包主要包含了下面的三个类:

  • Pattern 类:一个 Pattern 对象是正则表达式编译表示。 Pattern 类没有提供公共的构造函数。要创建一个 Pattern 对象,你必须首先调用他的公用静态编译方法来获得 Pattern 对象。这些方法的第一个参数是正则表达式。
  • Matcher 类:一个 Matcher 对象是用来解释模式和执行与输入字符串相匹配的操作。和 Pattern 类一样 Matcher 类也是没有构造方法的,你需要通过调用 Pattern 对象的 matcher 方法来获得 Matcher 对象。
  • PatternSyntaxException: 一个 PatternSyntaxException 对象是一个不被检查的异常,来指示正则表达式中的语法错误。

捕获组的概念

捕获组可以通过从左到右计算其开括号来编号,编号是从1 开始的。例如,在正则表达式 ( (A) (B (C) ) )中,存在四个这样的组:

1—–((A)(B(C)))
2—–(A)
3—–( B (C) )
4—–(C)

其实还有一个0组,始终代表整个表达式。
至于为什么要说这个捕获组呢,因为很快就会用到了

非捕获组

既然有捕获组那就有非捕获组

建议看完其他内容后最后再看这个

非捕获组(non-capturing): (?:X) 、(?=X)、 (?<=X)、 (?!X)、 (?<!X)
这里就只是简单的说下吧
(?:X):我们知道了分组用group(index)可以获得指定组的匹配结果,那么(?:X)的作用就是只分组不捕获,就是说匹配的时候还是管用的,但是如果它是在第二组,使用group(2)的时候并不会获得它,会跳过,获得的是第三组的结果
(?=X):举个例子[0-9a-z]{2}(?=aa)意思就是是两位字符(数字,或字母),且后面紧跟着两个a。但是使用while循环匹配group()获取的时候虽然匹配aa但是不会显示在匹配结果中。这里需要注意的是当第二次搜索的时候是从第一次匹配的aa
(?<=):和上面差不多,不一样的是它是匹配前面的,也就是要放在前面
(?!)和(?<!):不多说了举两个栗子吧:
[0-9a-z]{2}(?!aa) 意思是:匹配两个字符,且后面紧跟着的不是aa
(?<=aa)[0-9a-z]{2} 意思是:匹配两个字符,且前面紧跟着的不是aa

Pattern

前面说过这个类可以认为是负责编译正则的,如果书写的正则表达式有错误那么它就会报错
然后就说下常用的几个方法

分割字符串

1
2
3
Pattern p=Pattern.compile("\\d+"); 
String[] str=p.split("我的QQ是:456456我的电话是:0532214我的邮箱是:[email protected]");
// 结果:str[0]="我的QQ是:" str[1]="我的电话是:" str[2]="我的邮箱是:[email protected]"

说白了就是用p去分割字符串

快速匹配

有一个静态方法是:Pattern.matcher(String regex,CharSequence input) 可以快速让我们知道某个字符串是否符合某个规则

1
2
Pattern.matches("\\d+","2223");//返回true
Pattern.matches("\\d+","2223aa");//返回false,需要匹配到所有字符串才能返回true,这里aa不能匹配到

Matcher

好了,重头戏来了,前面说过获取Mather必须由Pattern来,也就是Pattern.matcher方法
Pattern类只能做一些简单的匹配操作,要想得到更强更便捷的正则匹配操作,那就需要将Pattern与Matcher一起合作.Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持.
下面是官方API里的例子,典型调用顺序

1
2
3
4
5
6
7
Pattern p = Pattern.compile("a*b"); //编译
Matcher m = p.matcher("aaaaab"); //获取结果
boolean b = m.matches(); //使用结果

//上面三句可以写成一句
//但是对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。
boolean b = Pattern.matches("a*b", "aaaaab");

如果写成一句,那就是编译加匹配,编译还是蛮耗时的,所以上面一行代码的适合不频繁使用的情况

匹配操作的三个方法

首先说明三个方法均返回boolean类型,当匹配到时返回true,没匹配到则返回false

  • Matcher.matches()
    对整个字符串进行匹配,只有整个字符串都匹配了才返回true

    1
    2
    3
    4
    5
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("22bb23");
    m.matches();//返回false,因为bb不能被\d+匹配,导致整个字符串匹配未成功.
    Matcher m2=p.matcher("2223");
    m2.matches();//返回true,因为\d+匹配到了整个字符串
  • Matcher.lookingAt()
    lookingAt()对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true

    1
    2
    3
    4
    5
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("22bb23");
    m.lookingAt();//返回true,因为\d+匹配到了前面的22
    Matcher m2=p.matcher("aa2223");
    m2.lookingAt();//返回false,因为\d+不能匹配前面的aa
  • Matcher.find()
    find()对字符串进行匹配,匹配到的字符串可以在任何位置,不再多说
    此方法从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始

获得信息

这里同样也有常用的三个方法

  • start() 返回匹配到的子字符串在字符串中的索引位置.
  • end() 返回匹配到的子字符串的最后一个字符在字符串中的索引位置.
  • group() 返回匹配到的子字符串
    准确的说是:返回由以前匹配操作所匹配的输入子序列。
1
2
3
4
5
6
7
Pattern p=Pattern.compile("\\d+"); 
Matcher m=p.matcher("aaa2223bb");
m.find();//匹配2223

m.start();//返回3
m.end();//返回7,返回的是2223后的索引号
m.group();//返回2223

如果没有匹配到的话返回的就是0、字符串长度、原字符串

分组的使用

利用上面find的特性可以使用while循环全匹配

1
2
3
4
5
6
7
8
9
10
Pattern p=Pattern.compile("\\d+"); 
Matcher m=p.matcher("我的QQ是:456456 我的电话是:0532214 我的邮箱是:[email protected]");
while(m.find()) {
System.out.println(m.group());
}

// 输出
//456456
//0532214
//123

使用分组的话,类似这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Pattern r = Pattern.compile("(\\d+)(test.*)");
Matcher m = r.matcher("abc23333test123");

if (m.find()) {
// 第一个是原字符串哦
System.out.println("Found value: " + m.group(0));
System.out.println("Found value: " + m.group(1));
System.out.println("Found value: " + m.group(2));
} else {
System.out.println("NO MATCH");
}
//结果:
//Found value: 23333test123
//Found value: 23333
//Found value: test123

贪婪与非贪婪

这里还是再说下吧,贪婪就是尽可能多的匹配,默认就是这种模式,这种也很好理解,不多说
重要的是非贪婪匹配,一般带有量词以及?的都是非贪婪吧….就是尽可能少的匹配
下面是常见的几种非贪婪匹配模式:

*?重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

参考

http://www.cnblogs.com/ggjucheng/p/3423731.html

喜欢就请我吃包辣条吧!

评论框加载失败,无法访问 Disqus

你可能需要魔法上网~~