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\\[([^\\]]+)\\]";