簡介
本文介紹了 IBM Rational Team Concert(RTC)的代碼評審功能(Code Review)。這一功能可以使代碼評審流程變得更加規范,完善代碼提交流程;對于不同區域的成員可以更高效的協同工作,在代碼提交前發現到潛在的問題,盡快修復,提高代碼質量,有效減少缺陷數。
代碼評審的重要性
多數情況下,評審者能夠發現開發人員自身不能發現的問題或潛在問題,畢竟思維方式和考慮的點等會有差異
- 優秀的評審者通過評審,不僅可以發現開發人員的不足,更可以通過開發人員的代碼學到很多知識
- 對團隊而言,通過評審以及互相評審,了解到其他團隊成員負責的任務,必要時互相幫忙,互為后援,提高項目開發效率,降低項目風險
代碼評審的規則
- 從邏輯上講,本次修改是否符合需求,是否有類似的地方需要修改
- 可讀性上,是否有足夠的解釋說明,以便以后維護
- 就代碼規范而言,是否符合公司代碼規范,以保持代碼風格一致性
- 從代碼性能上講,是否有更有效的方案可以實現
- 單元測試(如果必要),測試用例是否能覆蓋本次的修改
RTC 對代碼評審的支持
作為目前主流的代碼管理工具,RTC 對代碼評審的功能已經有了很好的支持,比如利用郵件作為代碼提交者與評審者通信的工具,代碼評審過程中各個角色的劃分,代碼提交的權限設置等等,本節將具體介紹 RTC 在代碼評審過程中所涉及的概念及詳細配置。
對郵件的支持
在整個代碼評審過程中,郵件是作為代碼提交者及其他相關人員之間的重要通信工具,比如在代碼評審前提交、對代碼添加修改意見,團隊相關人員都應收到相應的郵件提醒,用戶可以通過如下配置是否啟用郵件支持:
- 打開 Repository Connections 界面并連接
圖 1. Repository 連接界面
- 打開用戶編輯窗口,如圖 2 所示:
圖 2. Open My User Editor
- 找到 Mail Configuration 頁面,進行相應的配置并保存,如圖 3 所示:
圖 3. 郵件配置界面
代碼評審中所涉及的角色的劃分
在整個代碼評審過程中,RTC 將會涉及到如下幾種角色
- Submitter:代碼提交者,由實現新功能的開發者自己擔任,可執行的操作有 Submit for review、Check-in,Deliver、Add Approver 等等。
- Review:代碼審查人員,負責代碼提交前細粒度的代碼審查工作,排除潛在的缺陷,一般由團隊中對所要修改的代碼比較熟悉的人員擔任。可執行的操作有 Add comment、Rejected、Approved 等。
- Approver:代碼評閱者,負責代碼提交前粗粒度的代碼審查工作,一般由資深開發人員及 tech lead 擔任,可執行的操作有 Add comments,Rejected、Approved 等。
- Verifier:功能的驗證者,對功能的實現作一些單元測試等等。
事實上對于以上這些角色,Submitter,Reviewer 和 Approver 是必須,Verifier 是可選的,用戶可以根據團隊實際情況決定在代碼評審過程中是否需要 Verifier。
代碼提交前的權限控制
RTC 在代碼提交時有了較好權限配置的支持,用戶(一般由 Project owner 或團隊的 tech lead 配置此權限)可以根據如下步驟進行配置:
- 連接自己所在的項目并打開,如圖 4 所示:
圖 4. 項目連接界面
- 切換到 Project Area 中的 Process Configuration 頁面,如圖 5 所示:
圖 5. 流程配置界面
- 雙擊 Team Configuration 中的 Operation Behavior 選項,如圖 6 所示:
圖 6. 操作行為界面
- 從右邊列表中選擇 Source Control 中的 Deliver(server)選項,雙擊對應 Everyone(default) 圖標,并雙擊 Add ... 按鈕添加代碼提交時的 Preconditions. 如圖 7 所示:
圖 7. Add Preconditions
- 在彈出的 Add Preconditions 對話框中選擇 Require Work Item Approval 選項,如圖 8 所示:
圖 8. Add Preconditions 界面
- 雙擊 Required approvals 欄中 new ... 按鈕添加代碼提交時的 Required Approval,針對不同的 Approval 類型選擇相應的 Approvers,單擊 ok 按鈕,最后保存所有配置。如圖 9 所示:
圖 9. 添加 Approval
經過上述一系列配置后,代碼提交者必須先取得相應的 Approval 之后才能提交代碼,從而達到代碼提交時的權限控制,保證代碼的質量。
RTC 代碼評審使用示例
在 RTC 中,代碼評審的流程大致如下,各個團隊可以根據實際情況進行優化。
圖 10. 代碼評審時序圖
下面我將以一個簡單的實例來說明在 RTC 中是如何進行代碼評審的:
- Check in 變更集
修改源代碼,在 RTC 客戶端中找到 Pending Changes 視圖,并將這些變更集 check in 到在 Jazz repository 上的 workspace,如圖 11 所示:
圖 11. Check in 變更集界面
- 關聯 work item
在 Pending Changes 視圖中,將 check in 的變更集關聯到相應的 work item(story 上的 task work item 或者是 issue 類型的 work item) 上。
圖 12. 關聯 work item 界面
- 提交代碼給相應的 approver review
在 Pending Changes 視圖中,找到相應的 Outgoing 變更集,點擊右鍵菜單中的 Submit for Review... 選項。
圖 13. Submit for Review 界面
- 添加注釋和相應的 Approver
在彈出的 submit for review 的對話框中添加相應的注釋及添加相應的 Approver 類型(具體類型請參考 RTC 中對代碼評審章節)。
圖 14. 添加注釋和 Approver 對話框
- 確定需要評審代碼關聯的 work item
Approver 將會根據 RTC 中關于代碼評審的郵件找到相應的 work item,并從 work item 中找到鏈接頁面。
圖 15. work item 鏈接界面
- 查找對應的變更集
Approver 從鏈接頁面中找到需要評審的變更集,雙擊此變更集,變更集將會在 RTC 客戶端的變更視圖中顯示。
圖 16. 查看變更集界面
- 給出評審結果及意見
每個 Approver 根據代碼評審的實際情況給出相應的修改意見和評審意見,如對于哪一行代碼需要修改或者同意提交等等,具體操作如圖 17 所示:
圖 17. 代碼評審界面
如果給出的評審結果為同意提交,則 submitter 直接進入代碼提交階段。如在此階段給出的評審結果為拒絕,則 submitter 需要從 work item 的 overview 視圖或 RTC 郵件中查看 Approver 添加的修改意見,并根據意見進行代碼修改,重新提交代碼評審。
- 代碼提交
代碼 Submitter 在 Pending Changes 視圖中找到相應的 Outgoing 變更集并提交。
RTC 代碼評審的注意事項
一次代碼評審和所提交的一個變更集是一一對應的關系,當對一個變更集提交代碼評審后,這個變更集就被凍結,此后對其中任何文件的修改都將通過另一新的變更集來跟蹤。所以,對于新的修改,需要再次提交代碼評審。
評審者在應用被評審者的變更集進行代碼評審時,有時會和評審者本地的變更集產生沖突,此時只要將產生沖突的本地變更集暫停(Suspend),就能暫時避免沖突從而繼續進行評審。
RTC 代碼評審的不足及展望
雖然 RTC 已經能夠支持完整的代碼評審功能,但在實際使用中還有一些改進之處。比如無法動態嵌入或鏈接到評論所涉及的代碼中的指定行,方便被評審者閱讀修改意見。而且評審的粒度較大,基于每個評審者的修改意見無法針對每條評論進行接收或拒絕。此外,如果加入代碼靜態分析功能,就能更快的找到問題,避免人為的疏漏。
為什么很多看起來不是很復雜的網站比如 Facebook、淘寶,需要大量頂尖高手來開發?
就拿淘寶來說說,當作給新人一些科普。
先說你看到的頁面上,最重要的幾個:
【搜索商品】——這個功能,如果你有幾千條商品,完全可以用select * from tableXX where title like %XX%這樣的操作來搞定。但是——當你有10000000000(一百億)條商品的時候,任何一個數據庫都無法存放了,請問你怎么搜索?這里需要用到分 布式的數據存儲方案,另外這個搜索也不可能直接從數據庫里來取數據,必然要用到搜索引擎(簡單來說搜索引擎更快)。好,能搜出商品了,是否大功告成可以啵 一個了呢?早著呢,誰家的商品出現在第一頁?這里需要用到巨復雜的排序算法。要是再根據你的購買行為做一些個性化的推薦——這夠一幫牛叉的算法工程師奮斗 終生了。
【商品詳情】——就是搜索完畢,看到你感興趣的,點擊查看商品的頁面,這個頁面有商品的屬性、詳細描述、評價、賣家信息等等,這個頁面的每天展示次數在 30億以上,同樣的道理,如果你做一個網站每天有10個人訪問,你絲毫感覺不到服務器的壓力,但是30億,要解決的問題就多了去了。首先,這些請求不能直 接壓到數據庫上,任何單機或分布式的數據庫,承受30億每天的壓力,都將崩潰到完全沒有幸福感,這種情況下要用到的技術就是大規模的分布式緩存,所有的賣 家信息、評價信息、商品描述都是從緩存里面來取到的,甚至更加極致的一點“商品的瀏覽量”這個信息,每打開頁面一次都要刷新,你猜能夠從緩存里面來取嗎? 淘寶做到了,整個商品的詳情都在緩存里面。
【商品圖片】——一個商品有5個圖片,商品描述里面有更多圖片,你猜淘寶有多少張圖片要存儲?100億以上。這么多圖片要是在你的硬盤里面,你怎么去查找 其中的一張?要是你的同學想拷貝你的圖片,你需要他準備多少塊硬盤?你需要配置多少大的帶寬?你們的網卡是否能夠承受?你需要多長時間拷貝給他?這樣的規 模,很不幸市面上已經沒有任何商業的解決方案,最終我們必須自己來開發一套存儲系統,如果你聽說過google的GFS,我們跟他類似,叫TFS。順便說 一下,騰訊也有這樣的一套,也叫TFS。
【廣告系統】——淘寶上有很多廣告,什么,你不知道?那說明我們的廣告做的還不錯,居然很多人不認為它是廣告,賣家怎么出價去買淘寶的廣告位?廣告怎么展示?怎么查看廣告效果?這又是一套算法精奇的系統。
【BOSS系統】——淘寶的工作人員怎么去管理這么龐大的一個系統,例如某時刻突然宣布某位作家的作品全部從淘寶消失,從數據庫到搜索引擎到廣告系統,里面的相關數據在幾分鐘內全部消失,這又需要一個牛叉的后臺支撐系統。
【運維體系】——支持這么龐大的一個網站,你猜需要多少臺服務器?幾千臺?那是零頭。這么多服務器,上面部署什么操作系統,操作系統的內核能否優 化?Java虛擬機能否優化?通信模塊有沒有榨取性能的空間?軟件怎么部署上去?出了問題怎么回滾?你裝過操作系統吧,優化過吧,被360坑過沒,崩潰過 沒?這里面又有很多門道。
不再多寫了,除了上面提到的這些,還有很多很多需要做的技術,當然并不是這些東西有多么高不可攀,任何復雜的龐大的東西都是從小到大做起來的,里面需要牛叉到不行的大犇,也需要充滿好奇心的菜鳥,最后這一句,你當我是別有用心好了。
功能上面雖然不復雜,但是要完成的細節卻很多. 比如news feed里面的推薦算法就很重要,要根據用戶之前的記錄和與好友的關系來生成. 另外就是根據用戶的信息和行為,要做機器學習和數據挖掘,從而來挑出最匹配的廣告.這也是比較花人力的事情.
另外Facebook的用戶量奇大無比. 假設你只是做一個學校內部用的社交網站, 那肯定很簡單. 但是如果考慮到上億人在上面用. 你首先服務器就必 須是一個分布式的機群,還要保證能抗住那么大的流量. 同時為了性能夠好,不得不加上mem cache和網頁分塊加載等功能. 還有就是每天用戶產生的總數據量(狀態,留言,照片,分享等)有TB的數量級,你數據庫是否撐住等等.
另外樹大招風,你要一個很強的安全小組來保證網站在受攻擊的時候能防御好,還有要防止垃圾信息和惡心廣告或者程序的散播. 另外還有為了全球化而帶來的多語言問題.
總之,一個網站做大了之后,很多問題就會產生,不是在校園里面做一個學期作業那么簡單.狼大人,休,行。
某個歷史上的大神曾經說過一句話:
要判斷一個算法的好壞,只要給它足夠的數據。
當用戶、數據和系統規模上到一個程度之后,所有曾經可以忽視的問題都會變得必須用從來不可想象的精力和技術去解決。
來來來 看看這個 剛看到的《當用戶點擊“舉報”后,Facebook在后臺會做哪些事情》
很多東西并不是表面看到的那樣簡單
身為前端攻城師,就這方面說一下這樣一個Facebook看起來“很簡單的網站”需要頂尖高手來開發和維護
寫前端程序要考慮很多,如下:可維護性,JS的執行高效性,JS文件的大小,用戶體驗等等
1. 可維護性
并不是所有人寫的程序都具有可維護性,清晰易懂的,這個區別在剛接觸編程和高手直接的差異體現的特別明顯
2. JS的執行高效性
一個網頁加載JS并執行,瀏覽器執行并渲染了半天還在渲染,相信很多用戶都不想看到吧?非常上海用戶體驗。
如何提升JS的執行速度呢?相信我,初學者大部分都是不知道的(排除寫過瀏覽器內核的同學),了解瀏覽器如何執行JS,如何渲染DOM能幫助開發者提升執行速度
3. JS文件的大小
JS文件或者HTML或者CSS文件過大,有很多缺點
第一,受網速影響,文件大,加載速度慢
第二,Facebook的用戶量非常巨大,每個人訪問就算多加載1KB(即使有cache,第一次總需要加載吧),可想而知,這個流量非常巨大,流量都是要錢的啊
4. 用戶體驗
略之
高手往往比非高手要注意的東西要多很多,這點相信大家不會質疑吧,只是就前端方面發表一些建議
如果要把一件簡單的事情搞復雜,你需要的是市場總監
如果要把一件簡單的事情搞簡單,你需要的是產品經理
如果要把一件復雜的事情搞復雜,你需要的是一堆碼農
如果要把一件復雜的事情搞簡單,你需要的是頂尖高手
明白了吧,頂尖高手的意義就在于讓你覺得這個東西看起來很簡單。
學“懂”計算機系統結構之后,理解這個問題比較容易點吧。
比如,你打開知乎,簡單的敲下幾行字,點擊提交,然后你看到了你的評論,這復雜嗎?不復雜。
1、為什么知乎要用瀏覽器才能打開呢,記事本不能訪問知乎?為什么用輸入自己的知乎用戶名和密碼才能訪問呢,我QQ密碼為嘛不能用?為什么我只能看到我關注內容,而不是網站所有用戶的所有內容呢?
2、當敲下鍵盤時,電腦是如何識別按下的具體哪個字符呢?是如何經過到達的CPU呢?CPU進行了如何的處理操作呢?顯示器為什么可以顯示相應的字符呢?
3、當點擊“提交”時,發生哪些變化呢?顯示的內容是保存了在本地電腦上了,還是保存在了知乎服務器上了呢?從本地的數據是如何傳輸到知乎服務器呢?從物 理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層這一系列的過程提交的評論內容傳輸形式是經過一系列的如何變化過程呢?
PS.對于一個字符從輸入到最后結果輸出的處理流程我也沒搞徹底清楚。隨便說說。。。希望有高手能具體解釋下啊。

手上沒有網站的結構層次示意圖,隨便拿張圖說明下原因吧。像計算機最初問世的時候,操作計算機的用戶既是設計者也是維護者的時代已經過去。每個節點都應該 是一個屬于一個節點的專屬內容,對個每個節點都應該是更清晰化更簡單化的:用戶的操作的應該簡單化,網絡的傳輸應該簡單化,數據的存儲也應該是簡單化。因 此對于用戶來說只需要用戶界面操作就足夠了,沒必要把數據庫之類的東西也交給用戶處理的。
public class FindA{
public static void main(String args[])
throws Exception{
String candidate =
"A Matcher examines the results of applying a pattern.";
String regex = "\\ba\\w*\\b";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(candidate);
String val = null;
System.out.println("INPUT: " + candidate);
System.out.println("REGEX: " + regex +"\r\n");
while (m.find()){
val = m.group();
System.out.println("MATCH: " + val);
}
if (val == null) {
System.out.println("NO MATCHES: ");
}
}
}
\b表示單詞的邊界,w表示任意的可構成單詞的字母數字,*表示前面的字母(當然可以
是更復雜的組之類的了東東)重復0次或0次以上,a當然還是a了。所以這個regex就
匹配單詞開頭為a的單詞了。
二、下面總結一下基本的正則表達式的meta character以及它們含義:
. 匹配任意一個字符 $ 匹配一行的結尾 ^ 匹配一行的開頭(在[]里面表示否定)
{} 定義了一個范圍 [] 定義了一個字符類 () 定義了一個組
*前面出現0次以上 + 前面匹配一次以上 ?前面出現0次或一次
\ 后面的字符不會看作metacharacter \w 字母數字下劃線 \W 非字母數字下劃線
\d 單個數字 \D單個非數字 | 或,二者之一 &&與操作符 \b單詞邊界
下面看看幾個簡單的例子:
[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]] a 到 z,除了 b 和 c:[ad-z](減去)
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](減去)
\\ 反斜杠
\t 間隔 ('\u0009')
\n 換行 ('\u000A')
\r 回車 ('\u000D')
\d 數字 等價于[0-9]
\D 非數字 等價于[^0-9]
\s 空白符號 [\t\n\x0B\f\r]
\S 非空白符號 [^\t\n\x0B\f\r]
\w 單獨字符 [a-zA-Z_0-9]
\W 非單獨字符 [^a-zA-Z_0-9]
\f 換頁符
\e Escape
\b 一個單詞的邊界
\B 一個非單詞的邊界
\G 前一個匹配的結束
^為限制開頭
^java 條件限制為以Java為開頭字符
$為限制結尾
java$ 條件限制為以java為結尾字符
. 條件限制除\n以外任意一個單獨字符
java.. 條件限制為java后除換行外任意兩個字符
加入特定限制條件「[]」
[a-z] 條件限制在小寫a to z范圍中一個字符
[A-Z] 條件限制在大寫A to Z范圍中一個字符
[a-zA-Z] 條件限制在小寫a to z或大寫A to Z范圍中一個字符
[0-9] 條件限制在小寫0 to 9范圍中一個字符
[0-9a-z] 條件限制在小寫0 to 9或a to z范圍中一個字符
[0-9[a-z]] 條件限制在小寫0 to 9或a to z范圍中一個字符(交集)
[]中加入^后加再次限制條件「[^]」
[^a-z] 條件限制在非小寫a to z范圍中一個字符
[^A-Z] 條件限制在非大寫A to Z范圍中一個字符
[^a-zA-Z] 條件限制在非小寫a to z或大寫A to Z范圍中一個字符
[^0-9] 條件限制在非小寫0 to 9范圍中一個字符
[^0-9a-z] 條件限制在非小寫0 to 9或a to z范圍中一個字符
[^0-9[a-z]] 條件限制在非小寫0 to 9或a to z范圍中一個字符(交集)
在限制條件為特定字符出現0次以上時,可以使用「*」
J* 0個以上J
.* 0個以上任意字符
J.*D J與D之間0個以上任意字符
在限制條件為特定字符出現1次以上時,可以使用「+」
J+ 1個以上J
.+ 1個以上任意字符
J.+D J與D之間1個以上任意字符
在限制條件為特定字符出現有0或1次以上時,可以使用「?」
JA? J或者JA出現
限制為連續出現指定次數字符「{a}」
J{2} JJ
J{3} JJJ
文字a個以上,并且「{a,}」
J{3,} JJJ,JJJJ,JJJJJ,???(3次以上J并存)
文字個以上,b個以下「{a,b}」
J{3,5} JJJ或JJJJ或JJJJJ
兩者取一「|」
J|A J或A
Java|Hello Java或Hello
「()」中規定一個組合類型
比如,我查詢<a href=\"index.html\">index</a>中<a href></a>間的數據,可寫作<a.*href=\".*\">(.+?)</a>
在使用Pattern.compile函數時,可以加入控制正則表達式的匹配行為的參數:
Pattern Pattern.compile(String regex, int flag)
flag的取值范圍如下:
Pattern.CANON_EQ 當且僅當兩個字符的"正規分解(canonical decomposition)"都完全相同的情況下,才認定匹配。比如用了這個標志之后,表達式"a\u030A"會匹配"?"。默認情況下,不考慮"規 范相等性(canonical equivalence)"。
Pattern.CASE_INSENSITIVE(?i) 默認情況下,大小寫不明感的匹配只適用于US-ASCII字符集。這個標志能讓表達式忽略大小寫進行匹配。要想對Unicode字符進行大小不明感的匹 配,只要將UNICODE_CASE與這個標志合起來就行了。
Pattern.COMMENTS(?x) 在這種模式下,匹配時會忽略(正則表達式里的)空格字符(譯者注:不是指表達式里的"\\s",而是指表達式里的空格,tab,回車之類)。注釋從#開始,一直到這行結束。可以通過嵌入式的標志來啟用Unix行模式。
Pattern.DOTALL(?s) 在這種模式下,表達式'.'可以匹配任意字符,包括表示一行的結束符。默認情況下,表達式'.'不匹配行的結束符。
Pattern.MULTILINE
(?m) 在這種模式下,'^'和'$'分別匹配一行的開始和結束。此外,'^'仍然匹配字符串的開始,'$'也匹配字符串的結束。默認情況下,這兩個表達式僅僅匹配字符串的開始和結束。
Pattern.UNICODE_CASE
(?u) 在這個模式下,如果你還啟用了CASE_INSENSITIVE標志,那么它會對Unicode字符進行大小寫不明感的匹配。默認情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。
Pattern.UNIX_LINES(?d) 在這個模式下,只有'\n'才被認作一行的中止,并且與'.','^',以及'$'進行匹配。
拋開空泛的概念,下面寫出幾個簡單的Java正則用例:
◆比如,在字符串包含驗證時
//查找以Java開頭,任意結尾的字符串
Pattern pattern = Pattern.compile("^Java.*");
Matcher matcher = pattern.matcher("Java不是人");
boolean b= matcher.matches();
//當條件滿足時,將返回true,否則返回false
System.out.println(b);
◆以多條件分割字符串時
Pattern pattern = Pattern.compile("[, |]+");
String[] strs = pattern.split("Java Hello World Java,Hello,,World|Sun");
for (int i=0;i<strs.length;i++) {
System.out.println(strs[i]);
}
◆文字替換(首次出現字符)
Pattern pattern = Pattern.compile("正則表達式");
Matcher matcher = pattern.matcher("正則表達式 Hello World,正則表達式 Hello World");
//替換第一個符合正則的數據
System.out.println(matcher.replaceFirst("Java"));
◆文字替換(全部)
Pattern pattern = Pattern.compile("正則表達式");
Matcher matcher = pattern.matcher("正則表達式 Hello World,正則表達式 Hello World");
//替換第一個符合正則的數據
System.out.println(matcher.replaceAll("Java"));
◆文字替換(置換字符)
Pattern pattern = Pattern.compile("正則表達式");
Matcher matcher = pattern.matcher("正則表達式 Hello World,正則表達式 Hello World ");
StringBuffer sbr = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sbr, "Java");
}
matcher.appendTail(sbr);
System.out.println(sbr.toString());
◆驗證是否為郵箱地址
String str="ceponline@yahoo.com.cn";
Pattern pattern = Pattern.compile("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
System.out.println(matcher.matches());
◆去除html標記
Pattern pattern = Pattern.compile("<.+?>", Pattern.DOTALL);
Matcher matcher = pattern.matcher("<a href=\"index.html\">主頁</a>");
String string = matcher.replaceAll("");
System.out.println(string);
◆查找html中對應條件字符串
Pattern pattern = Pattern.compile("href=\"(.+?)\"");
Matcher matcher = pattern.matcher("<a href=\"index.html\">主頁</a>");
if(matcher.find())
System.out.println(matcher.group(1));
}
◆截取http://地址
//截取url
Pattern pattern = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:]+");
Matcher matcher = pattern.matcher("dsdsds<http://dsds//gfgffdfd>fdf");
StringBuffer buffer = new StringBuffer();
while(matcher.find()){
buffer.append(matcher.group());
buffer.append("\r\n");
System.out.println(buffer.toString());
}
◆替換指定{}中文字
String str = "Java目前的發展史是由{0}年-{1}年";
String[][] object={new String[]{"\\{0\\}","1995"},new String[]{"\\{1\\}","2007"}};
System.out.println(replace(str,object));
public static String replace(final String sourceString,Object[] object) {
String temp=sourceString;
for(int i=0;i<object.length;i++){
String[] result=(String[])object[i];
Pattern pattern = Pattern.compile(result[0]);
Matcher matcher = pattern.matcher(temp);
temp=matcher.replaceAll(result[1]);
}
return temp;
}
◆以正則條件查詢指定目錄下文件
//用于緩存文件列表
private ArrayList files = new ArrayList();
//用于承載文件路徑
private String _path;
//用于承載未合并的正則公式
private String _regexp;
class MyFileFilter implements FileFilter {
/**
* 匹配文件名稱
*/
public boolean accept(File file) {
try {
Pattern pattern = Pattern.compile(_regexp);
Matcher match = pattern.matcher(file.getName());
return match.matches();
} catch (Exception e) {
return true;
}
}
}
/**
* 解析輸入流
* @param inputs
*/
FilesAnalyze (String path,String regexp){
getFileName(path,regexp);
}
/**
* 分析文件名并加入files
* @param input
*/
private void getFileName(String path,String regexp) {
//目錄
_path=path;
_regexp=regexp;
File directory = new File(_path);
File[] filesFile = directory.listFiles(new MyFileFilter());
if (filesFile == null) return;
for (int j = 0; j < filesFile.length; j++) {
files.add(filesFile[j]);
}
return;
}
/**
* 顯示輸出信息
* @param out
*/
public void print (PrintStream out) {
Iterator elements = files.iterator();
while (elements.hasNext()) {
File file=(File) elements.next();
out.println(file.getPath());
}
}
public static void output(String path,String regexp) {
FilesAnalyze fileGroup1 = new FilesAnalyze(path,regexp);
fileGroup1.print(System.out);
}
public static void main (String[] args) {
output("C:\\","[A-z|.]*");
}
@import url(http://www.tkk7.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);