SECTION 00 ORO 的典故
Jakarta ORO 所提供的是一组 Java classes , 包括 Perl5 兼容的 reqular expression, AWK-相似 的 reqular expression, glob expressions, 及一些工具, 让开发人员方便去替换, 切割, 过滤一些字串. 就是 ORO 所出的 OROMatcher, AwkTools, PerlTools, and TextTools 的继承产品 !
这些产品原本是 ORO 公司所研发的, 1998 年中他们解散了, 但是 ORO 这个名字纳入了 savarese.org , 让他不再是商业化的产品, 并且 Daniel Savarese ( 又是一个天才 ) 让这个 oro 延续下来, 让他成为 Opensource. 在 2000 的六月, OROMatcher 2.0, PerlTools 2.0, 还有较早版本的 AwkTools 及 TextTools 捐赠给 Jakarta Project , ORO 除了 jakarta-oro 之外还有 NetComponents 成为了 Jakarta Commons Net. 其实是一家了不起的公司, 造福了许多 Java 的开发人员
SECTION 01 Regular Expression
很多程序都支持 Regular Expression , 包括 Perl, PHP, Python, JavaScript, and JScript, 现在也很多编辑器是使用 Regular Expression 来做有效的搜速与替换的功能. 接下来, 我会说明 什么是 regular expression. JDK 1.4 也已经加入 java.util.regex.*, 代表 Regular Expression 的重要性越来越大.
Simple:是不用区分大小写的和出现位置的
- RE: soft
- Match: Softleader, software, Javasoft, Microsoft, i2software
The period notation :用 "." 来替换一个字符
- RE: s.o
- Match: sso, soo, sto, s#o, s o
The bracket notation :用 "[]" 来限制替换的字符集来取代一个字符
- RE: s[aeio]o
- Match: sao, seo, sio, soo
The OR operator :用 "()" 来限制替换的字符集来取代数个字符, 用 "|" 分隔.
- RE: s(aa|i|o)o
- Match: saao, sio, soo
The quantifier notations : 用以下的方式限定出现的字符次数,"*":0 到多, "+": 1到多, "?": 0 到 1, "{n}":n个, "{n,m}": n到m个.
电话:99-99999999
- RE: [0-9]{2}\-[0-9]{8}
- Match: 02-89519456 , 02-89519554
电话:99-99999999 或 9999999999
- RE: [0-9]{2}\-?[0-9]{8}
- Match: 02-89519456 , 02-89519554 , 0289519999
身份证字号: A999999999
- RE: [A-Z]{1}[0-9]{9}
- Match: A111111111, B123456789, Z987654321
The NOT notation :用 "^" 来禁止替换的字符来取代某个字符
- RE: [^B]1
- Match: A1
- Not Match: A2,B1,B2
The parentheses and space notations :用 "\s" 来设置空白字符
美国表示日期格式
- RE: [a-z]+\s+[0-9]{1,2},\s*[0-9]{4}
- Match: June 20, 2003
Other miscellaneous notations : 特殊的替换符号定义, 为了方便使用.
- \d [0-9]
- \D [^0-9]
- \w [A-Z0-9]
- \W [^A-Z0-9]
- \s [ \t\n\r\f]
- \S [^ \t\n\r\f]
SECTION 02 Jakarta-ORO
我只是简略地列出常用的状态, 有兴趣的可以到 google 查询 Regular Expression Tutorial, 应该可以查到很多资料让你参考研究.
ORO 也提供了
测试的 Applet 让你思考是否要抓取出 Match 的资料.
至于这个 Applet 的 source 放在 /src/java/examples/MatcherDemoApplet.java
我们拿这个例子来说明
public void search(){
int matchNum, group, caseMask, exprChoice, search;
String text;
MatchResult result;
Pattern pattern;
PatternMatcherInput input;
resultArea.setText("");
text = expressionField.getText();
exprChoice = expressionChoice.getSelectedIndex();
caseMask = CASE_MASK[exprChoice][caseChoice.getSelectedIndex()];
resultArea.appendText("Compiling regular expression.\n");
try {
pattern = compiler[exprChoice].compile(text, caseMask);
} catch(MalformedPatternException e){
resultArea.appendText("\nMalformed Regular Expression:\n" +
e.getMessage());
return;
}
search = searchChoice.getSelectedIndex();
text = inputArea.getText();
matchNum = 0;
resultArea.appendText("\nSearching\n\n");
if(search == MATCHES_SEARCH) {
if(matcher[exprChoice].matches(text, pattern))
resultArea.appendText("The input IS an EXACT match.\n");
else
resultArea.appendText("The input IS NOT an EXACT match.\n");
} else {
input = new PatternMatcherInput(text);
while(matcher[exprChoice].contains(input, pattern)) {
int groups;
result = matcher[exprChoice].getMatch();
++matchNum;
resultArea.appendText("Match " + matchNum + ": " +
result.group(0)+ "\n");
groups = result.groups();
if(groups > 1){
resultArea.appendText(" Subgroups:\n");
for(group=1; group < groups; group++){
resultArea.appendText(" " + group + ": " +
result.group(group) + "\n");
}
}
}
resultArea.appendText("\nThe input contained " + matchNum + " matches.");
}
}
基本上是先产生一个 compiler, 接著设置 pattern, 最后使用 Matcher 来过滤
SECTION 03 后记
jakarta-oro 可以利用在很多地方, 包括上周介绍的 HTML Parsing 判断, Logging 的解析, 只要有规则的字串或文章, 我们都可以利用之来得到需要的资料.
Log 的范例 From Javaworld
- LOG:"172.26.155.241 - - [26/Feb/2001:10:56:03 -0500] \"GET /IsAlive.htm HTTP/1.0\" 200 15 ";
- REG:"([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})\\s-\\s-\\s\\[([^\\]]+)\\]";