標籤:
http://lavasoft.blog.51cto.com/
http://lavasoft.blog.51cto.com/62575/179324
JavaRegex應用總結
一、概述 Regex是Java處理字串、文本的重要工具。 Java對Regex的處理集中在以下兩個兩個類:java.util.regex.Matcher 模式類:用來表示一個編譯過的Regex。java.util.regex.Pattern 匹配類:用模式比對一個字串所表達的抽象結果。(很遺憾,Java Doc並沒有給出這兩個類的職責概念。) 比如一個簡單例子:import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Regex例子
*
* @author leizhimin 2009-7-17 9:02:53
*/
public class TestRegx {
public static void main(String[] args) {
Pattern p = Pattern.compile("f(.+?)k");
Matcher m = p.matcher("fckfkkfkf");
while (m.find()) {
String s0 = m.group();
String s1 = m.group(1);
System.out.println(s0 + "||" + s1);
}
System.out.println("---------");
m.reset("fucking!");
while (m.find()) {
System.out.println(m.group());
}
Pattern p1 = Pattern.compile("f(.+?)i(.+?)h");
Matcher m1 = p1.matcher("finishabigfishfrish");
while (m1.find()) {
String s0 = m1.group();
String s1 = m1.group(1);
String s2 = m1.group(2);
System.out.println(s0 + "||" + s1 + "||" + s2);
}
System.out.println("---------");
Pattern p3 = Pattern.compile("(19|20)\\d\\d([- /.])(0[1-9]|1[012])\\2(0[1-9]|[12][0-9]|3[01])");
Matcher m3 = p3.matcher("1900-01-01 2007/08/13 1900.01.01 1900 01 01 1900-01.01 1900 13 01 1900 02 31");
while (m3.find()) {
System.out.println(m3.group());
}
}
} 輸出結果:fck||c
fkk||k
---------
fuck
finish||in||s
fishfrish||ishfr||s
---------
1900-01-01
2007/08/13
1900.01.01
1900 01 01
1900 02 31
Process finished with exit code 0
二、一些容易迷糊的問題 1、Java對反斜線處理的問題 在其他語言中,\\表示要插入一個字元\;在Java語言中,\\表示要插入Regex的反斜線,並且後面的字元有特殊意義。 看API文檔:預定義字元類. 任何字元(與行結束符可能匹配也可能不匹配)\d 數字:[0-9]\D 非數字: [^0-9]\s 空白字元:[ \t\n\x0B\f\r]\S 非空白字元:[^\s]\w 單詞字元:[a-zA-Z_0-9]\W 非單詞字元:[^\w] 但是看看上面程式,對比下不難看出:\d在實際使用的時候就寫成了 \\d; 在JavaRegex中,如果要插入一個\字元,則需要在Regex中寫成\\\\,原因是下面的APIDoc定義\\表示一個反斜線。但是如果在正則表示式中表示斷行符號換行等,則不需要多添加反斜線了。比如斷行符號\r就寫作\r. 字元x 字元 x\\ 反斜線字元\0n 帶有八進位值 0 的字元 n (0 <= n <= 7)\0nn 帶有八進位值 0 的字元 nn (0 <= n <= 7)\0mnn 帶有八進位值 0 的字元 mnn(0 <= m <= 3、0 <= n <= 7)\xhh 帶有十六進位值 0x 的字元 hh\uhhhh 帶有十六進位值 0x 的字元 hhhh\t 定位字元 (‘\u0009‘)\n 新行(換行)符 (‘\u000A‘)\r 斷行符號符 (‘\u000D‘)\f 換頁符 (‘\u000C‘)\a 警示 (bell) 符 (‘\u0007‘)\e 轉義符 (‘\u001B‘)\cx 對應於 x 的控制符 2、Matcher.find():嘗試尋找與模式比對的字元序列的下一個子序列。此方法從字元序列的開頭開始,如果該方法的前一次調用成功了並且從那時開始匹配器沒有被重設,則從以前匹配操作沒有匹配的第一個字元開始,即如果前一次找到與模式比對的子序列則這次從這個子序列後開始尋找。 3、Matcher.matchers():判斷整個字元序列與模式是否匹配。當連續用Matcher對象檢查多個字串時候,可以使用Matcher.reset():重設匹配器,放棄其所有顯式狀態資訊並將其添加位置設定為零。或者Matcher.reset(CharSequence input) 重設此具有新輸入序列的匹配器。來重複使用匹配器。 4、組的概念,這個概念很重要,組是用括弧劃分的Regex,可以通過編號來引用組。組號從0開始,有幾對小括弧就表示有幾個組,並且組可以嵌套,組號為0的表示整個運算式,組號為1的表示第一個組,依此類推。例如:A(B)C(D)E正則式中有三組,組0是ABCDE,組1是B,組2是D;A((B)C)(D)E正則式中有四組:組0是ABCDE,組1是BC,組2是B;組3是C,組4是D。 int groupCount():返回匹配其模式中組的數目,不包括第0組。String group():返回前一次匹配操作(如find())的第0組。String group(int group):返回前一次匹配操作期間指定的組所匹配的子序列。如果該匹配成功,但指定組未能匹配字元序列的任何部分,則返回 null。int start(int group):返回前一次匹配操作期間指定的組所匹配的子序列的初始索引。int end(int group):返回前一次匹配操作期間指定的組所匹配的子序列的最後索引+1。 5、匹配的範圍的控制最變態的就要算lookingAt()方法了,名字很讓人迷惑,需要認真看APIDoc。 start() 返回以前匹配的初始索引。end() 返回最後匹配字元之後的位移量。 public boolean lookingAt()嘗試將從地區開頭開始的輸入序列與該模式比對。與 matches 方法類似,此方法始終從地區的開頭開始;與之不同的是,它不需要匹配整個地區。如果匹配成功,則可以通過 start、end 和 group 方法擷取更多資訊。返回:若且唯若輸入序列的首碼匹配此匹配器的模式時才返回 true。 6、Pattern標記 Pattern類的靜態方法static Pattern compile(String regex, int flags) 將給定的Regex編譯到具有給定標誌的模式中。其中的flags參數就是Pattern標記,這個標記在某些時候非常重要。 Pattern.CANON_EQ 啟用規範等價。Pattern.CASE_INSENSITIVE 啟用不區分大小寫匹配。Pattern.COMMENTS 模式中允許空白和注釋。Pattern.DOTALL 啟用 dotall 模式。Pattern.LITERAL 啟用模式的字面值分析。Pattern.MULTILINE 啟用多行模式。Pattern.UNICODE_CASE 啟用 Unicode 感知的大小寫摺疊。Pattern.UNIX_LINES 啟用 Unix 行模式。
三、字串的替換 String.replace(char oldChar, char newChar) 返回一個新的字串,它是通過用 newChar 替換此字串中出現的所有 oldChar 而產生的。String.replace(CharSequence target, CharSequence replacement) 使用指定的字面值替換序列替換此字串匹配字面值目標序列的每個子字串。String.replaceAll(String regex, String replacement) 使用給定的 replacement 字串替換此字串匹配給定的Regex的每個子字串。String.replaceFirst(String regex, String replacement) 使用給定的 replacement 字串替換此字串匹配給定的Regex的第一個子字串。 StringBuffer.replace(int start, int end, String str) 使用給定 String 中的字元替換此序列的子字串中的字元。StringBuilder.replace(int, int, java.lang.String) 使用給定 String 中的字元替換此序列的子字串中的字元。 Matcher.replaceAll(String replacement) 替換模式與給定替換字串相匹配的輸入序列的每個子序列。Matcher.replaceFirst(String replacement) 替換模式與給定替換字串匹配的輸入序列的第一個子序列。
四、字串的切分 String[] split(String regex) 根據給定的Regex的匹配來拆分此字串。 String[] split(String regex, int limit) 根據匹配給定的Regex來拆分此字串。 當然,還有一個StringTokenizer類,可以用來切分字串,但是現在SUN已經不推薦使用了。轉變下思路,其實用Regex也可以達到將字串切分為段的目的。
五、沒有提到的 Regex的API簡單好用,沒太多複雜的地方,並非不重要,Regex最大的痛點在於熟練書寫Regex。有關Regex的規範,在Pattern類APIdoc中都有非常詳細的介紹,而且條理清晰,在此就不贅述了。
JavaRegex應用總結