学习这个东西,菜鸟主要参考的是这两篇文章: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
上面这个例子菜鸟纠结蛋疼的试了半天。
警句:菜鸟用爪挖,看者需谨慎,切莫听一面之词,徒走曲折之路。