学习这个东西,菜鸟主要参考的是这两篇文章:Java正则多字符串匹配替换(网址:http://www.jb51.net/article/34154.htm)、学习正则表达式:Matcher类(网址:http://www.java3z.com/cwbwebhome/article/article8/81313.html?id=3138)
首先要看懂下面的符号的意思
[...] 位于括号之内的任意字符
[^...] 不在括号之中的任意字符
. 除了换行符之外的任意字符,等价于[^\n]
\w 任何单字字符, 等价于[a-zA-Z0-9]
\W 任何非单字字符,等价于[^a-zA-Z0-9]
\s 任何空白符,等价于[\ t \ n \ r \ f \ v]
\S 任何非空白符,等价于[^\ t \ n \ r \ f \ v]
\d 任何数字,等价于[0-9]
\D 除了数字之外的任何字符,等价于[^0-9]
[\b] 一个退格直接量(特例)
{n, m} 匹配前一项至少n次,但是不能超过m次
{n, } 匹配前一项n次,或者多次
{n} 匹配前一项恰好n次
? 匹配前一项0次或1次,也就是说前一项是可选的. 等价于 {0, 1}
+ 匹配前一项1次或多次,等价于{1,}
* 匹配前一项0次或多次.等价于{0,}
| 选择.匹配的要么是该符号左边的子表达式,要么它右边的子表达式
(...) 分组.将几个项目分为一个单元.这个单元可由 *、+、?和|等符号使用,而且还可以记住和这个组匹配的字符以供此后引用使用
\n 和第n个分组所匹配的字符相匹配.分组是括号中的子表达式(可能是嵌套的).分组号是从左到右计数的左括号数
^ 匹配的是字符的开头,在多行检索中,匹配的是一行的开头
$ 匹配的是字符的结尾,在多行检索中,匹配的是一行的结尾
\b 匹配的是一个词语的边界.简而言之就是位于字符\w 和 \w之间的位置(注意:[\b]匹配的是退格符)
\B 匹配的是非词语的边界的字符
Matcher类有个非常重要的概念叫做:组(Group)
例如:\w(\d\d)(w+)
这个正则表达式中是用()来划分组的:
第0组:不看括号,这个的表达式就是0组\w(\d\d)(w+)
第1组:(\d\d)
第2组:(\w+)
然后来做做例子:(为了使\是有效的所以要用\\放在字符串中)
1 import java.util.regex.Matcher;
2 import java.util.regex.Pattern;
3
4 public class Calender {
5 public static void main(String[] args) {
6 Pattern p = Pattern.compile("(\\d\\d)\\1");//第一组是(\\d\\d)表示2个任何数字,而后面的\1表示后面的两个数要和前面两个一样
7 String s = "1212";//可以改成2525之类的前两个和后两个相同的数字,但不能改成1213这样的(12和13不同)
8 Matcher m = p.matcher(s);//若是Pattern.compile("(\\d(\\d))\\2")则需改成122才对
9 if(m.find()){
10 int gc = m.groupCount();
11 for(int i = 0; i <= gc; i++)
12 System.out.println("group " + i + " :" + m.group(i));
13 }
14 }
15
16 }
输出结果为:
group 0 :1212
group 1 :12
现在来试一个验证邮箱的有效性的例子:
1 import java.util.regex.Matcher;
2 import java.util.regex.Pattern;
3
4 public class Calender {
5 public static void main(String[] args) {
6 /**
7 * ^要以字符为开头才能匹配
8 * 第一组:([a-z0-9_\\.\\-\\+]+)---a-z或0-9或_或.或-或+都可以匹配
9 * 第二组:([\\da-z\\.\\-]+)---数字或a-z或.或-都可以匹配
10 * 第三组:([a-z\\.]{2,6})---a-z或.匹配最少2次最多6次
11 * $要以字符为结尾才能匹配
12 */
13 Pattern p = Pattern.compile("^([a-z0-9_\\.\\-\\+]+)@([\\da-z\\.\\-]+)\\.([a-z\\.]{2,6})$");
14 String s = "test_-.+@qq.163.sina.com";
15 Matcher m = p.matcher(s);
16 if(m.find()){
17 int gc = m.groupCount();
18 for(int i = 0; i <= gc; i++)
19 System.out.println("group " + i + " :" + m.group(i));
20 }
21 }
22 }
输出结果为:
group 0 :test_-.+@qq.163.sina.com
group 1 :test_-.+
group 2 :qq.163.sina
group 3 :com
又来试试例子:
1 import java.util.regex.Matcher;
2 import java.util.regex.Pattern;
3
4 public class Calender {
5 public static void main(String[] args) {
6 /**
7 * 第一组:(name|value)---选择name如果没有则选择value
8 * \"---引号
9 * 第二组:(.+?)---.表示匹配除了换行符之外任意字符、+表示匹配前一项1或n次、?表示匹配前一项0或1次(表示前一项可选)
10 * 如果只是(.+)没有?则它一直要到第四个引号前才会停止
11 * 如果只是(.?)没有+则name的值必须是一个或零个字符的
12 * 不要把(.+?)理解成单纯的符号了
13 */
14 Pattern p = Pattern.compile("android:(name|value)=\"(.+?)\"");
15 String s = "<meta-data android:name=\"appid\" android:value=\"joy\"></meta-data>";
16 Matcher m = p.matcher(s);
17 if(m.find()){
18 int gc = m.groupCount();
19 for(int i = 0; i <= gc; i++)
20 System.out.println("group " + i + " :" + m.group(i));
21 }
22 }
23 }
输出结果:
group 0 :android:name="appid"
group 1 :name
group 2 :appid
上面这个例子菜鸟纠结蛋疼的试了半天。
警句:菜鸟用爪挖,看者需谨慎,切莫听一面之词,徒走曲折之路。