在计算理论或编译原理中曾经论述过用正则文法来做词法分析,所以正则文法具备表达任何字符串的能力。正则表达式的表达能力和正则文法相当,对于任何一类字符串描述,都可以用正则表达式表达。在实际的编程中,我们通常会遇到字符串匹配、过滤等操作,而这种操作往往可以通过正则表达式来解决;而一般常用的语言都会提供相应的语言库API来支持正则表达式,如Java的java.util.regex包下的Matcher类和Pattern类;以及对正则表达式具有全面支持和优化过的Jakarta-ORO库。
首先,我们来看一下正则表达式中字符的种类,在《编译原理》这门课中提到字符可以分成普通字符和元字符(metacharacter)两种。正则表达式中的元字符包括:^, $, ?, *, +, (, ), {, }, [, ], \, ., 等等,这些元字符或其组合具有特殊的含义,详见下述。那如何表示这些元字符表示的普通字符呢?比如,我需要一个正则表达式以‘?’开始,应该如何表示呢?是这样吗:^?[.]*;显然不是,正确的表示方法应该为:^\?[.]*,正则表达式采用反斜杠来进行转义,反斜杠后面跟元字符可以获得元字符对应的普通字符,如\\, \*, ...;反斜杠后面跟部分普通字符可以获得一些不可表示的字符,如\n, \t, \s, \S...
^:以开头 $:以结尾
例:^s.*a$è以s开头,以a结尾的字符串
?:重复0次或1次 *:重复0次或多次 +:重复1次及1次以上
例:a[cd]?可以匹配:a, ac, ad
{n}:重复n次 {m , n}:重复m~n次 {m,}:重复m次以上
[]: []中包含一系列字符,但只能匹配其中的任意一个,[]中所有特殊字符都将失去其特殊含义
正则表达式[]中,’-’有着特殊的意义,表示一个范围,对于’-’字符,需转义’\-’,在[]外则不需要转义
在’[]’中,’^’表示不想匹配的字符
():在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰
如:(abc)+è用于匹配abc, abcabc, abcabcabc…
abc+è用于匹配abc, abcc, abccc…
取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到(见示例)
\s:匹配所有空白字符,包括Tab字符
\S:匹配所有非空白字符[^\t\n\r\f]
\w: [a-zA-Z0-9]
\d:[0-9]
\D:[^0-9]
综上所述,我们发现正则表达式足以表示任意的字符串,元字符的类型可以分成以下几类:
边界标识:^, $
选择(switch):| , [] , [ - ] , [^ ]
重复(while):?, *, +, {m, n}
跟元字符(正则表达式中最重要的元字符):\
表示字符类别的方法有[ ] , \d, \D, \s, \S, \w, \W
还有需要注意的就是在字符类别[ ]内,元字符将失去意义而变成普通字符(^除外,^表示非的意思),还有就是 '-' 在[ ]内表示范围,在[ ]外表示普通字符
对于java中的正则表达式,需要注意的一点是’\’的使用,在java的正则表达式中,表示’\’需要使用”\\\\”,因为java中表示’\’需要使用’\\’,’\’在java中为转义字符(如回车表示为’\r’,换行表示为’\n’,反斜杠表示为’\\’,制表符表示为’\t’),所以当java读到字符串”\\\\”时,将其解释为’\\’作为正则表达式的输入,而在正则表达式中,’\’同样为转义字符,所以其表示反斜杠需要使用’\\’,因此对于java中的字符串”\\\\”,最终被解释为’\’。而对于正则表达式中的’\w’,’\d’,’\D’,’\s’,’\S’等表达式,在java中需写为’\\w’,’\\d’,’\\D’,’\\s’,’\\S’.
importorg.apache.oro.text.regex.MalformedPatternException;
importorg.apache.oro.text.regex.MatchResult;
importorg.apache.oro.text.regex.Pattern;
importorg.apache.oro.text.regex.PatternCompiler;
importorg.apache.oro.text.regex.PatternMatcher;
importorg.apache.oro.text.regex.Perl5Compiler;
importorg.apache.oro.text.regex.Perl5Matcher;
publicclassRegularExpression {
/**
*@paramargs
*/
publicstaticvoidmain(String[] args) {
//TODOAuto-generated method stub
PatternCompiler compiler =newPerl5Compiler();
try{
Pattern pattern = compiler.compile("(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\s-\\s-\\s\\[([^\\]]+)\\]");
String logEntry ="10.214.10.192 - - [2/Dec/1012 : 16:48:05 - 0500]\"GET /IsAlive.htm HTTP/1.0\"200 15";
PatternMatcher matcher =newPerl5Matcher();
if(matcher.contains(logEntry, pattern)){
MatchResult result = matcher.getMatch();
System.out.println("IP: "+ result.group(1));
System.out.println("TimeStamp: "+ result.group(2));
}
Pattern pattern1 = compiler.compile(".[a\\-z^]?");
String str1 ="a^";
System.out.println(matcher.matches(str1, pattern1));
}catch(MalformedPatternExceptione) {
//TODOAuto-generated catch block
e.printStackTrace();
}
}
}
输出结果为:
IP: 10.214.10.192
TimeStamp: 2/Dec/1012 : 16:48:05 - 0500
true