元字符
正則表達式使用一些特定的元字符來檢索、匹配和替換符合規則的字符串元字符:普通字符、標準字符、限定字符(量詞)、定位字符(邊界字符)正則表達式引擎
正則表達式是一個用正則符號寫出來的公式程序對正則表達式進行語法分析,建立語法分析樹再根據語法分析樹結合正則表達式引擎生成執行程序(狀態機),用於字符匹配正則表達式引擎是一套核心算法,用於建立狀態機小結正則表達式 => 語法分析樹語法分析樹 + 正則表達引擎 => 狀態機 => 用於字符匹配目前實現正則表達式引擎的方式有兩種NFA自動機
text="aabcab" regex="bc"
回溯
用NFA自動機實現的比較複雜的正則表達式,在匹配過程中經常會引起回溯問題大量的回溯會長時間佔用CPU,從而帶來系統性能開銷text="abbc" regex="ab{1,3}c"
讀取正則表達式第一個匹配符a和字符串第一個字符a進行比較,a對a,匹配
讀取正則表達式第二個匹配符b{1,3}和字符串的第二個字符b進行比較,匹配,但b{1,3}表示1~3個字符,而NFA自動機具有貪婪特性,所以不會讀取正則表達式的下一個匹配符c
使用b{1,3}和字符串的第四個字符c進行比較,發現不匹配,此時就會發生回溯
發生回溯後,讀取正則表達式的下一個匹配符c,和字符串的第四個字符c進行比較,結果匹配
避免回溯
避免回溯的方法:使用懶惰模式和獨佔模式
貪婪模式(Greedy)
在數量匹配中,如果單獨使用+、?、*、{min,max}等量詞,正則表達式會匹配儘可能多的內容text="abbc" , regex="ab{1,3}c",發生了一次匹配失敗,就會引起一次回溯text="abbbc" , regex="ab{1,3}c",匹配成功懶惰模式(Reluctant)
在懶惰模式下,正則表達式會儘可能少地重複匹配字符,如果匹配成功,會繼續匹配剩餘的字符串使用?開啟懶惰模式,text="abc" , regex="ab{1,3}?c"匹配結果是"abc",在該模式下NFA自動機首先選擇獨佔模式(Possessive)
和貪婪模式一樣,獨佔模式一樣會最大限度地匹配更多內容,但在匹配失敗時會結束匹配,不會發生回溯問題使用+開啟懶惰模式,text="abbc" , regex="ab{1,3}+bc"結果是不匹配,結束匹配,不會發生回溯問題代碼
match("ab{1,3}c", "abbc"); // abbc,貪婪模式,產生回溯 match("ab{1,3}c", "abbbc"); // abbbc,貪婪模式,不產生回溯 match("ab{1,3}?", "abbbb"); // ab,懶惰模式,不產生回溯 match("ab{1,3}+bc", "abbc"); // null,獨佔模式,不產生回溯
正則表達式的優化
少用貪婪模式,多用獨佔模式(避免回溯)減少分支選擇,分支選擇類型"(X|Y|Z)"的正則表達式會降低性能,儘量減少使用,如果一定要使用考慮選擇的順序,將比較常用的選擇放在前面,使它們可以較快地被匹配提取共用模式,(abcd|abef) => ab(cd|ef)如果是簡單的分支選擇類型,可以用三次index代替(X|Y|Z)捕獲組
String text = "test"; String reg = "()(.*?)()"; Pattern p = Pattern.compile(reg); Matcher m = p.matcher(text); while (m.find()) { System.out.println(m.group(0));// 整個匹配到的內容 System.out.println(m.group(1));//() System.out.println(m.group(2));//(.*?) System.out.println(m.group(3));//() // 輸出: // test // // test // }
非捕獲組
String text = "test"; String reg = "(?:)(.*?)(?:)"; Pattern p = Pattern.compile(reg); Matcher m = p.matcher(text); while (m.find()) { System.out.println(m.group(0));// 整個匹配到的內容 System.out.println(m.group(1));//(.*?) // 輸出 // test // test }
小結
在做好性能測試的前提下,可以使用正則表達式,否則能不用就不用,避免造成更多的性能問題.
文章的話到這裡就結束了,希望大家在性能測試中,對正則表達式有自己的認識。今日的性能篇到此結束!
需要更多源碼視頻,面試題,Java技術書籍等學習資料的
可以關注我獲取哦!私信我“學習”;即可領取!
我是小架,我們下篇文章見!