之前我们看了下正则的基本语法规则以及简单的正则创建和匹配写法。这里我们就重点关注下具体的匹配对象提供的一些方法,基本都过一遍,然后我们针对邮箱、电话等做一些练习(过程中不会的我们再回过头的复习一下)
一、Matcher 类的方法(pattern负责将匹配规则进行编译,然后匹配获得的对象为matcher,之后的操作都是通过Matcher提供)
1. 索引方法
索引方法
索引方法提供了有用的索引值,精确表明输入字符串中在哪能找到匹配:
序号方法及说明
1public int start()
返回以前匹配的初始索引。
2public int start(int group)
返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
3public int end()
返回最后匹配字符之后的偏移量。
4public int end(int group)
返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
开始实践之前了,我们先看一个组的概念:
捕获组
捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
例如,正则表达式 (dog) 创建了单一分组,组里包含"d","o",和"g"。
捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组:
((A)(B(C)))
(A)
(B(C))
(C)
可以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。
还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在 groupCount 的返回值中。
直接看实例比较好理解:
String patterns = "(ru)noob(.ppx)";
1. ()可以作为分组标识,比如上面的匹配规则中(ru)、(.ppx)分别为一个组
2. 其中组的顺序是从1开始,而0表示的是整个字串
需要find()到才能获取哟!!!!
///< 组的概念
String patternzu = "(ru)noob(.ppx)";
Pattern patternzzu = Pattern.compile(patternzu);
String contentzu = "from runoob.com. runoob. I am noob.ppx runoob.ppx I am noob";
Matcher matcherzu = patternzzu.matcher(contentzu);
System.out.println("匹配组个数: " + matcherzu.groupCount());
if (matcherzu.find()){
for (int i = 0; i <= matcherzu.groupCount(); ++i){
System.out.println("组(0表示整个字串): " + matcherzu.group(i));
}
}
结果:
匹配组个数: 2
组(0表示整个字串): runoob.ppx
组(0表示整个字串): ru
组(0表示整个字串): .ppx
其实还是蛮好理解的对吧!就是匹配规则利用()号进行了分组,有什么好处了?
比如我们匹配的规则很多,其中我们需要某个组的位置,用于精确找到要匹配的字串的索引,有什么用呢? ---- 最简单的就是替换
比如(img)sb_picture(.png), 我们需要找到所有的imgsb_picture.png,然后替换.png为.jpg,这个时候你通过public int start(int group)和public int end(int group)就可以获取对应的起始终止位置,进而实现准确的替换!!!
因为1. 你首先准确的找到了imgsb_picture.png
2. 进而又准确的替换掉了.png
现在我们再来看这个具体的方法案例就轻松些了
///< @1 回顾下基础用法
String content = "I am noob " +
"from runoob.com. runoob. I am noob.ppx runoob.ppx I am noob";
System.out.println("字符串长度=" + content.length());
String patterns = "(ru)noob(.ppx)";
boolean isMatch = Pattern.matches(patterns, content);
System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch);
///< @2 回顾下基础用法
Pattern pattern = Pattern.compile(patterns);
Matcher matcher = pattern.matcher(content);
System.out.println("字符串中是否包含了 'runoob' 子字符串? " + matcher.find());
///< matcher.find()相当于next的概念,所以用完后需要重新开始记得重置!
matcher.reset();
System.out.println("匹配组: " + matcher.groupCount());
if (matcher.find()){
System.out.println("全部串: " + matcher.group(0));
System.out.println("子串: " + matcher.group(1));
System.out.println("子串: " + matcher.group(2));
System.out.println("找到子串起始位置: " + matcher.start(1));
System.out.println("找到子串终止位置: " + matcher.end(1));
System.out.println("找到子串起始位置: " + matcher.start(2));
System.out.println("找到子串终止位置: " + matcher.end(2));
}
看结果:
匹配组: 2
全部串: runoob.ppx
子串: ru
子串: .ppx
找到子串起始位置: 50
找到子串终止位置: 52
找到子串起始位置: 56
找到子串终止位置: 60
就是这样呀呀呀!
2. 研究方法
研究方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:
序号方法及说明
1public boolean lookingAt()
尝试将从区域开头开始的输入序列与该模式匹配。
2public boolean find()
尝试查找与该模式匹配的输入序列的下一个子序列。
3public boolean find(int start)
重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
4public boolean matches()
尝试将整个区域与模式匹配。
然后我们看案例吧,,,比较直接
find() - 就是类似next的用法,不停找下一个
find(int start) - 跳过一些位置开始找
matches() - 整个完全匹配是否成功的标识
lookingAt() - 需要从第一个字符开始就匹配
matches 和 lookingAt 方法都用来尝试匹配一个输入序列模式。它们的不同是 matches 要求整个序列都匹配,而lookingAt 不要求。
lookingAt 方法虽然不需要整句都匹配,但是需要从第一个字符开始匹配。
这两个方法经常在输入字符串的开始使用。
看案例
///< 研究方法
Pattern patternb = Pattern.compile("abc");
Matcher matcherb = patternb.matcher("abc");
while (matcherb.find()){
System.out.println("找到子串起始位置: " + matcherb.start());
System.out.println("找到子串终止位置: " + matcherb.end());
}
System.out.println("找到子串终止位置: " + matcherb.find());
System.out.println("找到子串终止位置: " + matcherb.lookingAt());
System.out.println("找到子串终止位置: " + matcherb.matches());
结果:
找到子串起始位置: 0
找到子串终止位置: 3
找到子串终止位置: false
找到子串终止位置: true
找到子串终止位置: true
3. 替换方法
替换方法是替换输入字符串里文本的方法:
序号方法及说明
1public Matcher appendReplacement(StringBuffer sb, String replacement)
实现非终端添加和替换步骤。
2public StringBuffer appendTail(StringBuffer sb)
实现终端添加和替换步骤。
3public String replaceAll(String replacement)
替换模式与给定替换字符串相匹配的输入序列的每个子序列。
4public String replaceFirst(String replacement)
替换模式与给定替换字符串匹配的输入序列的第一个子序列。
5public static String quoteReplacement(String s)
返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。
replaceFirst 和 replaceAll 方法用来替换匹配正则表达式的文本。不同的是,replaceFirst 替换首次匹配,replaceAll 替换所有匹配。
///< 替换方法
String hellabct = "abcabc";
Pattern patternbt = Pattern.compile("abc");
Matcher matcherbt = patternbt.matcher(hellabct);
System.out.println(matcherbt.replaceFirst("def"));
System.out.println(matcherbt.replaceAll("def"));
结果:
defabc
defdef
4. append相关
appendReplacement是java中替换相应字符串的一个方法
appendReplacement(StringBuffer sb,String replacement)
将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个 StringBuffer 对象里
appendTail(StringBuffer sb)
将最后一次匹配工作后剩余的字符串添加到一个 StringBuffer 对象里
So, 一般是配合使用,核心就是:
while(m.find()){
m.appendReplacement(sb,REPLACE);
}
m.appendTail(sb);
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches
{
private static String REGEX = "a*b";
private static String INPUT = "aabfooaabfooabfoobkkk";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
// 获取 matcher 对象
Matcher m = p.matcher(INPUT);
StringBuffer sb = new StringBuffer();
while(m.find()){
m.appendReplacement(sb,REPLACE);
}
m.appendTail(sb);
System.out.println(sb.toString());
}
}
sb就是最终我们操作完成的结果: 相当于aabfooaabfooabfoobkkk -> -foo-foo-foo- + kkk
kkk就是m.appendTail(sb)获取的...
到这里还是好理解赛。 关键还是需要去实践,看概念。
二、PatternSyntaxException 类的方法
PatternSyntaxException 是一个非强制异常类,它指示一个正则表达式模式中的语法错误。
PatternSyntaxException 类提供了下面的方法来帮助我们查看发生了什么错误。
序号方法及说明
1public String getDescription()
获取错误的描述。
2public int getIndex()
获取错误的索引。
3public String getPattern()
获取错误的正则表达式模式。
4public String getMessage()
返回多行字符串,包含语法错误及其索引的描述、错误的正则表达式模式和模式中错误索引的可视化指示。
三方没有提供一个案例,我们就看看怎样用就行:
try{
System.out.println("找到子串起始位置: " + matcherb.start());
} catch (PatternSyntaxException ex) {
System.out.println("PatternSyntaxException: " + ex.getMessage());
//ex.printStackTrace();
}
就是捕获异常嘛。。。
到这里我们就暂时把这个相关方法过了一下,以后或许会用到....下一篇尝试实践邮箱、电话案例