这应该是比较常用的吧….可惜我忘了,还有字符串相关的方法使用频率也很高
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 | Pattern p=Pattern.compile("\\d+"); |
说白了就是用p去分割字符串
快速匹配
有一个静态方法是:Pattern.matcher(String regex,CharSequence input)
可以快速让我们知道某个字符串是否符合某个规则
1 | Pattern.matches("\\d+","2223");//返回true |
Matcher
好了,重头戏来了,前面说过获取Mather必须由Pattern来,也就是Pattern.matcher
方法
Pattern类只能做一些简单的匹配操作,要想得到更强更便捷的正则匹配操作,那就需要将Pattern与Matcher一起合作.Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持.
下面是官方API里的例子,典型调用顺序
1 | Pattern p = Pattern.compile("a*b"); //编译 |
如果写成一句,那就是编译加匹配,编译还是蛮耗时的,所以上面一行代码的适合不频繁使用的情况
匹配操作的三个方法
首先说明三个方法均返回boolean类型,当匹配到时返回true,没匹配到则返回false
Matcher.matches()
对整个字符串进行匹配,只有整个字符串都匹配了才返回true1
2
3
4
5Pattern 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()对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true1
2
3
4
5Pattern p=Pattern.compile("\\d+");
Matcher m=p.matcher("22bb23");
m.lookingAt();//返回true,因为\d+匹配到了前面的22
Matcher m2=p.matcher("aa2223");
m2.lookingAt();//返回false,因为\d+不能匹配前面的aaMatcher.find()
find()对字符串进行匹配,匹配到的字符串可以在任何位置,不再多说
此方法从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。
获得信息
这里同样也有常用的三个方法
- start() 返回匹配到的子字符串在字符串中的索引位置.
- end() 返回匹配到的子字符串的最后一个字符在字符串中的索引位置.
- group() 返回匹配到的子字符串
准确的说是:返回由以前匹配操作所匹配的输入子序列。
1 | Pattern p=Pattern.compile("\\d+"); |
如果没有匹配到的话返回的就是0、字符串长度、原字符串
分组的使用
利用上面find的特性可以使用while循环全匹配
1 | Pattern p=Pattern.compile("\\d+"); |
使用分组的话,类似这样
1 | Pattern r = Pattern.compile("(\\d+)(test.*)"); |
贪婪与非贪婪
这里还是再说下吧,贪婪就是尽可能多的匹配,默认就是这种模式,这种也很好理解,不多说
重要的是非贪婪匹配,一般带有量词以及?
的都是非贪婪吧….就是尽可能少的匹配
下面是常见的几种非贪婪匹配模式:
*?
重复任意次,但尽可能少重复
+?
重复1次或更多次,但尽可能少重复
??
重复0次或1次,但尽可能少重复
{n,m}?
重复n到m次,但尽可能少重复
{n,}?
重复n次以上,但尽可能少重复
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~