Java正則表示式API詳解
阿新 • • 發佈:2019-01-07
1. Pattern類
public class PatternExample { /** * public static String quote(String s) * 返回指定字串的字面值模式, 也就是說字串序列中的元字元和轉義序列將不具有特殊含義. * 會使用\Q \E包裹, \Q \E中間的字元是字面意思, 不具有特殊含義. * * public static Pattern compile(String regex, int flag) * 編譯給定正則表示式 * flag: 匹配標誌, 常用的如下解釋 * CASE_INSENSITIVE: 匹配時大小寫不敏感. * MULTILINE: 啟用多行模式, ^ $匹配行的開頭和結尾, 而不是整個輸入序列的的開頭和結尾. * UNIX_LINES: 啟用UNIX換行符, 在多行模式中使用^ $時只有\n被識別成終止符. * DOTALL: 在此模式中元字元.可以匹配任意字元, 包括換行符. * LITERAL: 啟用模式的字面值意思, 模式中的元字元、轉義字元不再具有特殊含義. * * public static boolean matches(String regex, String s) * 判斷整個輸入序列是否與給定的模式匹配. * 底層呼叫Matcher例項的matchers方法 */ @Test public void quote() { String regex1 = Pattern.quote(".java"); Assert.assertEquals("\\Q.java\\E", regex1); Matcher matcher = Pattern.compile(regex1).matcher("Effect.java"); Assert.assertTrue(matcher.find()); String regex2 = Pattern.quote("\\.java"); Assert.assertEquals("\\Q\\.java\\E", regex2); Assert.assertTrue(Pattern.compile(regex2).matcher("Effect\\.java").find()); Assert.assertFalse(Pattern.compile(regex2).matcher("Effect.java").find()); } @Test public void matchesVsFind() { String s = "satat"; String regex = "at"; Assert.assertFalse(Pattern.matches(regex, s)); Assert.assertTrue(Pattern.compile(regex).matcher(s).find()); Assert.assertFalse(Pattern.compile("^at").matcher(s).find()); }
2. Matcher
public class MatcherExample { /** * 匹配操作 * public boolean lookingAt() * 嘗試將整個輸入序列的開始處與模式匹配, 對於輸入序列的結尾處不做要求 * 也就是說從左(必須是序列的開頭)到右有一處與模式匹配, 便返回true. * * public boolean matches() * 嘗試將整個輸入序列與模式匹配, 只有從頭到尾完全與模式匹配才返回true. * * public boolean find() * 只要整個輸入序列或者子序列有一個與模式匹配, 便返回true. * find方法可用來尋找輸入序列中所有與模式匹配的子序列. * * 上述三個方法返回true時, 可以使用start, end, group方法獲取詳細資訊 * 返回false時或者沒有呼叫過匹配方法, 呼叫start, end, group會丟擲異常"No match available" * * public int start() * 返回匹配序列在輸入序列中的初始索引. * public int start(int group) * 返回給定組捕獲的匹配序列在輸入序列中的初始索引, 如果給定模式匹配成功, * 但是模式中的指定組沒有匹配返回-1. * 如果模式中沒有指定的組將丟擲異常IndexOutOfBoundsException: No group ${group} * * public int end() * 返回匹配序列中最後一個字元在輸入序列中的索引+1. * public int end(int group) * 返回給定組捕獲的匹配序列中最後一個字元在輸入序列中索引+1, * 如果給定模式匹配成功, 但是模式中的指定組沒有匹配返回-1. * 如果模式中沒有指定的組將丟擲異常IndexOutOfBoundsException: No group ${group} * * public String group() * 返回匹配序列 * public String group(int group) * 返回給定組捕獲的匹配序列. * 如果給定模式匹配成功, 但是模式中的指定組沒有匹配返回null. * 如果模式中沒有指定的組將丟擲異常IndexOutOfBoundsException: No group ${group} */ @Test public void match() { String goal = "at sat cat mat"; String regex = ".?at(a)?"; Matcher matcher = Pattern.compile(regex).matcher(goal); // 從開始處匹配 Assert.assertTrue(matcher.lookingAt()); Assert.assertEquals(0, matcher.start()); Assert.assertEquals(2, matcher.end()); Assert.assertEquals("at", goal.substring(matcher.start(), matcher.end())); Assert.assertEquals("at", matcher.group()); // 組1(a)沒有匹配到, 返回-1 Assert.assertEquals(-1, matcher.start(1)); Assert.assertEquals(-1, matcher.end(1)); Assert.assertNull(matcher.group(1)); } /** * 修改或讀取當前模式匹配輸入序列的範圍(區域), 預設是全部區域. * 查詢時包頭不包尾(subString()方法一樣的含義) */ @Test public void region() { String goal = "33abcd55"; String regex = "abcd"; Matcher matcher = Pattern.compile(regex).matcher(goal); // 查詢開始索引 Assert.assertEquals(0, matcher.regionStart()); // 查詢結尾索引 Assert.assertEquals(goal.length(), matcher.regionEnd()); Assert.assertFalse(matcher.matches()); matcher.reset(); // 調整區域, 相當於擷取${goal}的abcd來匹配. matcher.region(2, 6); Assert.assertTrue(matcher.matches()); Assert.assertEquals(2, matcher.regionStart()); Assert.assertEquals(6, matcher.regionEnd()); } @Test public void group() { String goal = "pig dog cat snake horse dog cat tiger monkey"; String regex = "(dog)\\s*(cat)\\s*?"; Matcher matcher = Pattern.compile(regex).matcher(goal); // 查詢所有與模式匹配的串 while (matcher.find()) { // result: dog cat System.out.println(matcher.group()); // result: [dog, cat] for (int i = 1; i <= matcher.groupCount(); i++) { if (i == 1) { System.out.print("[" + matcher.group(i)); } else if (i == matcher.groupCount()) { System.out.println(", " + matcher.group(i) + "]"); } else { System.out.print(", " + matcher.group(i)); } } System.out.println("-----------------"); } } /** * public Matcher appendReplacement(StringBuffer sb, String replacement) * 將目標字串與模式匹配的部分替換成replacement, 將結果放到sb中 * 此方法只會替換一處匹配的地方, 並且目標字串的後續部分不會存放到sb中 * 其中replacement可以使用反向引用來獲取捕獲組的內容 * 反向引用規則(僅適用於Java): * 1. 使用捕獲組編號, $n 其中0 <= n <=groupCount() * 2. 使用捕獲組名稱, ${name} name以非數字開頭 * replacement只會涉及到兩個字元的轉義: 1. $ -> \\$ 2. \ -> \\ * 例子: * String gaol = "I like music", regex = "like, replacement = "love"; * 那麼sb = I love * * StringBuffer appendTail(String sb) * 與appendReplacement搭配工作, 目標字串剩下的內容新增到sb中 * 接著上述例子呼叫appendTail方法, 那麼sb = I love music * * 基於以上兩個方法便能實現replaceFirst, replaceAll兩個方法 */ @Test public void replaceFist() { String goal = "I like music"; String regex = "like"; String relpacement = "love"; Matcher matcher = Pattern.compile(regex).matcher(goal); StringBuffer sb = new StringBuffer(); if (matcher.find()) { matcher.appendReplacement(sb, relpacement); Assert.assertEquals("I love", sb.toString()); matcher.appendTail(sb); Assert.assertEquals("I love music", sb.toString()); } } /** * 去掉dog 和 cat */ @Test public void replaceAll() { String goal = "pig dog snake cat horse dog cat tiger monkey"; String regex = "(dog\\s?)|(cat\\s?)"; Matcher matcher = Pattern.compile(regex).matcher(goal); StringBuffer sb = new StringBuffer(); boolean flag = false; while (matcher.find()) { matcher.appendReplacement(sb, ""); flag = true; } if(flag) { sb = matcher.appendTail(sb); Assert.assertEquals("pig snake horse tiger monkey", sb.toString()); } } /** * 去重 */ @Test public void removeDuplicate() { String goal = "aabbcddeefgg"; String regex = "(\\w)\\1+"; Matcher matcher = Pattern.compile(regex).matcher(goal); String result = matcher.replaceAll("$1"); Assert.assertEquals("abcdefg", result); } }