模式匹配
(一)“模式”是用于转换输入数据的规则。采用多种方式将数据与一个或多个逻辑结构进行比较、将数据分解为各个构成部分,或从数据中提取信息。
(二)正则表达式是代表具有特殊意义字符的字符串。从海量数据中寻找特定的信息时,正则表达式起到了至关重要的作用。正则表达式仿佛一个模板,将某个字符模式与所搜索的字符串进行匹配。在编写程序时正则表达式也起着很重要的作用,应用广泛。
(三)Java 的模式匹配配(from http://apps.hi.baidu.com/share/detail/3851069)
下面列出Java DOC中Pattern的部分内容,来介绍正则表达式的一些字符特性(翻译可能不正确,请指正):
一个正则表达式(用String指出),首先必须放到这个类中。作为结果,可以被用来创造一个Matcher的对象。这个对象可以根据正则表达式匹配任意的字符序列。所有这些都将在match端掉用,所以pattern可以被多个match共享。
一个典型的范例如下:
Pattern p = Pattern.compile(“a*b”);
Matcher m = p.matcher(“aaaaab”);
boolean b = m.matches();
当一个正则表达式只使用一次时,在这个类中定义matches是方便的。这个方法编辑了一个表达式并且匹配一个输入的序列。下面的表达式和上面三个表达式是等价的:boolean b = Pattern.matches(“a*b”,”aaaaab”);。但是因为这样就不允许Pattern重复使用,所以在重复匹配的情况下是没有任何效率可言的。
这是一个不可变类,并且对于多线程是安全的。Matcher类并不是安全的。
正则表达式摘要
结构 相匹配的内容
x 代表字母x
\\ 代表反斜杠
\0n 代表8进制数(0 <= n <= 7)
\0nn 代表8进制数(0 <= n <= 7)
\0mnn 代表8进制数(0 <= m <= 3 0 <= n <= 7)
\xhh 代表16进制数0xhh
\uhhhh 代表16进制数0xhhhh
\t 代表制表符(‘\u0009’)
\n 代表换行符(‘\u000A’)
\r 代表回车符(‘\u000D’)
\f 代表换页符(‘\u000C’)
\a 代表警铃(‘\u0007’)
\e 代表溢出(‘\u001B’)
\cX 代表Ctrl+X
字符级
[abc] a,b或c(只限于单字符)
[^abc] 除a,b或c之外的任意字符(否定)
[a-zA-Z] 从a到z或者从A到Z(范围)
[a-d[m-p]] 从a到d或m到p:[a-dm-p](联合)
[a-z&&[def]] d,e或f(交叉)
[a-z&&[^bc]] 从除b和c之外的a到z的字符:[ad-z](减少)
[a-z&&[^m-p]] 从a到z的区域中m到p之后剩下的区域:[a-lq-z](减少)
预先确定的字符集
. 任何一个字符
\d 0到9的数字[0-9]
\D 非数字[^0-9]
\s 空白的字符:[\t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 文字字符:[a-zA-Z_0-9]
\W 非文字字符:[^\w]
POSIX字符集(只能用于英语)
\p{Lower} 小写字母字符:[a-z]
\p{Upper} 大写字母字符:[A-Z]
\p{ASCII} 所有的ASCII码:[\x00-\x7F]
\p{Alpha} 所有字母字符:[\p{Lower}\p{Upper}]
\p{Digit} 所有十进制数据:[0-9]
\p{Alnum} 文字数字(包括文字和数字):[\p{Alpha}\p{Digit}]
\p{Punct} 标点符号,包括:!”#$%&’()*+,-./:;ó?@[\]^_`{|}~
\p{Graph} 可见字符:[\p{Alnum}\p{Punct}]
\p{Print} 打印字符:[\p{Graph}\x20]
\p{Blank} 空格或制表[ \t]
\p{Cntrl} 控制字符:[\x00-\x1F\x7F]
\p{XDigit} 十六进制数:[0-9a-fA-F]
\p{Space} 空白字符:[ \t\n\x0B\f\r]
java.lang.Character字符集
\p{javaLowerCase} 相当于java.lang.Character.isLowerCase()
\p{javaUpperCase} 相当于java.lang.Character.isUpperCase()
\p{javaWhitespace} 相当于java.lang.Character.isWhitespace()
\p{javaMirrored} 相当于java.lang.Character.isMirrored()
Unicode块和目录
\p{InGreek} 希腊块的字符集
\p{Lu} 大写字母
\p{Sc} 流通符号
\P{InGreek} 非希腊字符
分界匹配
^ 一行的开始
$ 一行的结束
\b 单词的分界
\B 非单词分界
\A 输入开始
\G 之前匹配的结束
\Z 输入的结束,但不是整个结束
\z 输入结束
重复量词
X? X重复0次或1次
X* X重复0次或多次
X+ X重复1次或多次
X{n} X重复n次
X{n,} X重复至少n次
X{n,m} X至少重复n次,至多重复m次
Reluctant quantifiers
X?? X重复0次或1次
X*? X重复0次或0次以上
X+? X重复1次或以上
X{n}? X重复n次
X{n,} X至少重复n次
X{n,m} X至少重复n次,至多重复m次
Possessive quantifiers
X?+ X重复1次或0次
X*+ X重复0次或0次以上
X++ X重复1次或1次以上
X{n}+ X重复n次
X{n,}+ X至少重复n次
X{n,m}+ X至少重复n次,至多重复m次
逻辑操作符
X.Y 将X和Y相连
X|Y 要么X要么Y
(X) X作为一个捕获
有了上面的知识,我们可以写一个正则表达式。比如我要用Java规定的这些符号来表示一个Email地址,就可以这样写:[a-zA-Z0-9_]+[@][a-zA-Z0-9]+[\.][com][\.cn]?
[a-zA-Z0-9_]+表示a到z,A到Z,0到9,外加下划线重复1次以上所组成的字符串,比如 yuetian_wang1982这样的就符合上面的这个正则表达式。(其余的部分不做细致检查,这个正则表达式是临时写的,只是表达一个意思,可能并不完整,没有经过测试,建议不要再真正的项目中使用)
Java中的实现:Pattern类与Matcher类
首先,Pattern中有一个静态方法,可以接受一个正则表达式,如:
String regex = "[a-zA-Z0-9_]+[@][a-zA-Z0-9]+[\.][com][\.cn]?";
Pattern pattern = Pattern.compile(regex);
然后用matcher方法来匹配要匹配的字符串,matcher方法会返回一个Matcher类,来查找匹配结果如:
String context = "checkhere1@hotmail.com ;checkhere2@hotmail.com"
Matcher matcher = pattern.matcher(context.toString());
最后通过matcher中的find()方法来查找有没有匹配的纪录,如果有返回true,如果没有返回false。通过group()方法来得到匹配的字符串,如:
while (matcher.find()) {
System.out.println(matcher.group());
}
输出结果应该是: checkhere1@hotmail.com