正则表达式
正则表达式是处理字符串的强大工具,它并不是java的特性.但是java有一套工具类提供了正则表达式的匹配功能.
用途
- 字符串匹配
 - 字符串查找
 - 字符串替换
 
Java类
java中正则表达式主要包括两个类:
- Pattern: 此对象是一个正则表达式的编译表示.此类没有共有的构造方法,只能通过静态编译方法来获得一个Pattern对象.比如Pattern.compile(“\d”); 这个样子.参数就是要编译的正则表达式.
 - Matcher: 是对输入字符串进行解释和匹配的引擎,它也没有公共的构造方法,只能通过Pattern对象的match方法来获得一个Matcher对象
 
Java中的正则表达式语法
首先说明java 中的正则表达式与普通的不一样,java中 ‘\‘ 表示的是要插入一个正则表达式的反斜杠,所以之后的字符具有特殊意义.所以在java中一个’\‘代表着其他语言中的一个’\’.为什么这么做呢,是因为java中字符串是不能有’\’的,如果有的话就必须得插入’\‘表示转义.所以在java字符串中就有了’\‘表示正则中的一个’\’了.这是java语言要求的.
下面来看一下具体用法
| 字符 | 说明 | 举例 | 
|---|---|---|
| \ | 将下一个字符标记为特殊字符,就是转义字符. | 例如 ‘\n’ 匹配 换行, ‘\\‘匹配’\‘. | 
| ^ | 匹配字符流的第一个字符 | 例如”^d.*” 匹配 以d开头的字符串 | 
| $ | 匹配字符流的最后一个字符 | 如上 | 
| * | 零次或多次匹配前一个字符 | 例如 “zo*” 匹配 “zoo” 和 “z” “zo” | 
| + | 一次或多次匹配前一个字符 | 例如 “zo+” 匹配 “zoo” 和 “zo” 但是不匹配 “z” | 
| ? | 匹配零次或一次之前的字符 | 例如 “1?” 匹配”1” 和 “” 空 | 
| {n} | n为非负数,正好匹配前一个字符n次 | 例如 “o{2}” 匹配 “oo” | 
| {n,} | n为非负数,匹配至少n此 | 如上 | 
| {n,m} | 匹配n到m次之前的字符 | 如上 | 
| . | 匹配任意字符 | 例如 “a.” 匹配 “ab” “ac” “ad”等 | 
| (pattern) | 匹配 pattern 并捕获该匹配的子表达式. | 例如 “(ab?)” 匹配 “a” “ab” | 
| x|y | 匹配x或者y字符 | “a|b” 匹配 “a” 或 “b” | 
| [^abc] | 反向字符集 匹配非括号内的字符 | “[^123]” 匹配不是字符1 2 3 的所有字符 | 
| [a-z] | 匹配a到z之间的所有字符 | |
| \b | 边界字符 | 例如 “er\b” 匹配 “never”中的er,但是不匹配”verb”中的er | 
| \B | 非边界字符 | 和上面反过来 | 
| \d | 匹配数字字符 | |
| \D | 匹配非数字字符 | |
| \n | 换行符 | |
| \s | 匹配任意空白字符 | 包括空格符,制表符,换页符 | 
| \S | 匹配任意非空白字符 | |
| \w | 匹配任意字类字符 | |
| \W | 匹配任意非字类字符 | 
Pattern
具体看看Pattern的用法,对象如其名,是一个匹配模式的编译表示.在java中不能直接构造出来,只能通过静态方法complie()来获取Pattern实例.1
2Pattern pattern =  Pattern.compile("\\d+");
System.out.println(pattern.pattern()); // 输出 \d+
此语句就返回一个匹配模式,此模式匹配全部的数字.
Pattern.split(CharSequence input)
Pattern 有一个split方法,这个方法与String.split()方法是一样的.返回用指定字符分割的字符数组1
2
3Pattern pattern =  Pattern.compile("\\d+");
String[] strs =  pattern.split("nihao123hello123word");
[nihao, hello, word]  // 输出
matches(String regex, CharSequence input)
这个方法是返回一个boolean值,判断输入是否与指定模式匹配.这里匹配是要全部匹配1
2
3Pattern.matches("\\d+","12312312");  //true
Pattern.matches("\\d+","123a12312"); //false  a不匹配
System.out.println(Pattern.matches("\\d+","")); // false ,+ 说明一个或多个,空不匹配
matcher(CharSequence input)
返回一个Matcher类,Matcher类提供了比Pattern更为多的功能,它能够匹配多次,并且有分组支持.
Matcher类方法
matchers() / lookingAt() / find()
Matcher类提供了三个匹配操作方法,三个方法都返回boolean值,匹配到时返回true,匹配不到返回false .
matchers()方法是对整个字符串进行匹配,只有整个字符串都匹配了才返回true
lookingAt() 只是对开头的字符进行匹配,只要开头有符合的,就返回true
find()对字符串匹配,匹配到的字符串可以在任意位置.1
2
3
4
5
6
7
8
9
10
11
12
13Pattern pattern =  Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher("223322");
        matcher.matches();  // true
        matcher.lookingAt(); // true
        matcher.find(); // true 
        Matcher m2 = pattern.matcher("2233dd");
        m2.matches(); // false  全部匹配才可以
        m2.lookingAt(); // true  开头有匹配的可以
        m2.find(); // true 任意地方匹配
        Matcher m3 = pattern.matcher("dd2233");
        m3.matches(); // false
        m3.lookingAt(); // false 开头没有匹配
        m3.find(); // true 任意有匹配可以
start() / end() / group()
使用matchers(),lookingAt(),find()方法后就可以使用这三个方法得到更加详细的信息
start() 返回匹配的子字符串在索引中的位置
end() 返回匹配的子字符串的最后一个字符在索引的位置
group() 返回匹配到的子字符串. 分组是在自己定义的匹配模式中定义的.用()包起来的.
这里分组有一个规定 :
捕获组是通过从左至右计算其开括号来编号,第一个括号编号从1开始.例如表达式中((A)(B(C))).编号从从1开始是如下的:
- ((A)(B(C)))
 - (A)
 - (B(C))
 - (C)
 
代码实例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 这里只介绍group操作,可以把group操作想成是m.group()操作看成是s.substring(m.start(),m.end());
Pattern p = Pattern.compile("(\\d+)((abc)+)");
Matcher matcher1 = p.matcher("900abcabc");
System.out.println(matcher1.matches()); // true 匹配到了整个字符串
System.out.println(matcher1.group()); // 返回整个字符串
System.out.println(matcher1.group(1)); // 第一个匹配的 全部的数字 所以是 900
System.out.println(matcher1.group(2)); // 第二个匹配的 abcabc
System.out.println(matcher1.group(3)); // 第三个括号 一个abc
// 下面看lookingAt()方法
Pattern p1 = Pattern.compile("(\\d+)(abc)");
Matcher matcher2 = p1.matcher("900abcbbd");
matcher2.lookingAt(); // true  looking只需要匹配开头就可以了.所以这里是true,如果用matches则返回false
System.out.println(matcher2.group(1)); // 900 匹配第一个括号中的内容
System.out.println(matcher2.group(2)); // abc 后面的则不匹配
find方法,find方法比较不一样,所以需要单独来讲1
2
3
4
5
6
7
8
9
10        Pattern p2 = Pattern.compile("(\\d+)(a+)");
        Matcher matcher3 = p2.matcher("900aa bcbb900aa bcbb900aa bcbbabc");
        while (matcher3.find()){
            System.out.println(matcher3.group());
        }
        
输出
900aa   
900aa
900aa
find方法将会找到整个串中所有符合的子串.当然也可以使用group(1)匹配第一个分组,从而找到所有的字符串.在这里有一个点就是因为find()方法会匹配整个字符串符合模式的子串.所以每次调用find()方法,就会找到下一个匹配此模式的子串.所以在调用了一次find()方法就需要在调用一次group()方法来获得所匹配的子串.这是因为在matcher中记录了一个当前匹配的位置,下一次在匹配的时候会从当前位置开始进行匹配.
appendReplacement(StringBuffer sb, String replacement) 和 appendTail(StringBuffer sb)
appendReplacement这个方法主要是为了用来为字符串做替换的.通过将匹配到的字符串替换成指定的字符串到字符串缓冲区.appendTail从添加位置开始从字符序列读取字符然后加入到缓冲区.一般是用来给appendReplacement方法替换过之后调用它来复制剩余的序列.
1  | Pattern p3 = Pattern.compile("cat");  |