您好,登錄后才能下訂單哦!
本篇內容主要講解“Java正則表達式中Pattern類怎么用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java正則表達式中Pattern類怎么用”吧!
在Java中,java.util.regex包定義了正則表達式使用到的相關類,其中最主要的兩個類為:Pattern、Matcher:
Pattern 編譯正則表達式后創建一個匹配模式;
Matcher 使用Pattern實例提供的正則表達式對目標字符串進行匹配,是真正影響搜索的對象。。
另加一個新的例外類,PatternSyntaxException,當遇到不合法的搜索模式時,會拋出例外。
聲明:public final class Pattern implements java.io.Serializable
Pattern 類有final修飾,可知他不能被子類繼承。
含義:模式類,正則表達式的編譯表示形式。
注意:此類的實例是不可變的,可供多個并發線程安全使用。
compile( )方法有一個版本,它需要一個控制正則表達式的匹配行為的參數:
Pattern Pattern.compile(String regex, int flag)
flag 的取值范圍
字段 | 說明 |
---|---|
Pattern.UNIX_LINES | unix行模式,大多數系統的行都是以\n結尾的,但是少數系統,比如Windows,卻是以\r\n組合來結尾的,啟用這個模式之后,將會只以\n作為行結束符,這會影響到^、$和點號(點號匹配換行符)。 通過嵌入式標志表達式 (?d) 也可以啟用 Unix 行模式。 |
Pattern.CASE_INSENSITIVE | 默認情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。這個標志能讓表達式忽略大小寫進行匹配。要想對Unicode字符進行大小不明感的匹配,只要將UNICODE_CASE與這個標志合起來就行了。 通過嵌入式標志表達式(?i)也可以啟用不區分大小寫的匹配。 指定此標志可能對性能產生一些影響。 |
Pattern.COMMENTS ??????????????? | 這種模式下,匹配時會忽略(正則表達式里的)空格字符(不是指表達式里的”//s”,而是指表達式里的空格,tab,回車之類)和注釋(從#開始,一直到這行結束)。 通過嵌入式標志表達式(?x) 也可以啟用注釋模式。 |
Pattern.MULTILINE | 默認情況下,輸入的字符串被看作是一行,即便是這一行中包好了換行符也被看作一行。當匹配“^”到“$”之間的內容的時候,整個輸入被看成一個一行。啟用多行模式之后,包含換行符的輸入將被自動轉換成多行,然后進行匹配。 通過嵌入式標志表達式 (?m) 也可以啟用多行模式。 |
Pattern.LITERAL | 啟用字面值解析模式。 指定此標志后,指定模式的輸入字符串就會作為字面值字符序列來對待。輸入序列中的元字符或轉義序列不具有任何特殊意義。 標志 CASE_INSENSITIVE 和 UNICODE_CASE 在與此標志一起使用時將對匹配產生影響。其他標志都變得多余了。 不存在可以啟用字面值解析的嵌入式標志字符。 |
Pattern.DOTALL | 在這種模式中,表達式 .可以匹配任何字符,包括行結束符。默認情況下,此表達式不匹配行結束符。 通過嵌入式標志表達式 (?s) 也可以啟用此種模式(s 是 “single-line” 模式的助記符,在 Perl 中也使用它)。 |
Pattern.UNICODE_CASE | 在這個模式下,如果你還啟用了CASE_INSENSITIVE標志,那么它會對Unicode字符進行大小寫不敏感的匹配。默認情況下,大小寫不明感的匹配只適用于US-ASCII字符集。 指定此標志可能對性能產生影響。 |
Pattern.CANON_EQ | 當且僅當兩個字符的正規分解(canonical decomposition)都完全相同的情況下,才認定匹配。比如用了這個標志之后,表達式a/u030A會匹配?。默認情況下,不考慮規范相等性(canonical equivalence)。 指定此標志可能對性能產生影響。 |
在這些標志里面,Pattern.CASE_INSENSITIVE,Pattern.MULTILINE,以及Pattern.COMMENTS是最有用的(其中Pattern.COMMENTS還能幫我們把思路理清楚,并且/或者做文檔)。注意,你可以用在表達式里插記號的方式來啟用絕大多數的模式。這些記號就在上面那張表的各個標志的下面。你希望模式從哪里開始啟動,就在哪里插記號。
可以用OR (|)運算符把這些標志配合使用。
我測試了一下,也就是說如果沒有 MULTILINE 標志的話, ^ 和 $ 只能匹配輸入序列的開始和結束;否則,就可以匹配輸入序列內部的行結束符。測試代碼如下:
import java.util.regex.*; /** * 多行模式 */ public class ReFlags_MULTILINE { public static void main(String[] args) { // 注意里面的換行符 String str = "hello world\r\n" + "hello java\r\n" + "hello java"; System.out.println("===========匹配字符串開頭(非多行模式)==========="); Pattern p = Pattern.compile("^hello"); Matcher m = p.matcher(str); while (m.find()) { System.out.println(m.group() + " 位置:[" + m.start() + "," + m.end() + "]"); } System.out.println("===========匹配字符串開頭(多行模式)==========="); p = Pattern.compile("^hello", Pattern.MULTILINE); m = p.matcher(str); while (m.find()) { System.out.println(m.group() + " 位置:[" + m.start() + "," + m.end() + "]"); } System.out.println("===========匹配字符串結尾(非多行模式)==========="); p = Pattern.compile("java$"); m = p.matcher(str); while (m.find()) { System.out.println(m.group() + " 位置:[" + m.start() + "," + m.end() + "]"); } System.out.println("===========匹配字符串結尾(多行模式)==========="); p = Pattern.compile("java$", Pattern.MULTILINE); m = p.matcher(str); while (m.find()) { System.out.println(m.group() + " 位置:[" + m.start() + "," + m.end() + "]"); } } }
===========匹配字符串開頭(非多行模式)===========
hello 位置:[0,5]
===========匹配字符串開頭(多行模式)===========
hello 位置:[0,5]
hello 位置:[13,18]
hello 位置:[25,30]
===========匹配字符串結尾(非多行模式)===========
java 位置:[31,35]
===========匹配字符串結尾(多行模式)===========
java 位置:[19,23]
java 位置:[31,35]
有的時候,需要進行忽略大小寫的匹配。該例子實現匹配攝氏溫度和華氏溫度,對于以C、c、F和f結尾的溫度值都能匹配。
import java.util.regex.Pattern; public class ReFlags_CASE_INSENSITIVE { public static void main(String[] args) { System.out.println("===========API忽略大小寫==========="); String moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*[CF]"; Pattern p = Pattern.compile(moneyRegex,Pattern.CASE_INSENSITIVE); System.out.println("-3.33c " + p.matcher("-3.33c").matches()); System.out.println("-3.33C " + p.matcher("-3.33C").matches()); System.out.println("===========不忽略大小寫==========="); moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*[CF]"; p = Pattern.compile(moneyRegex); System.out.println("-3.33c " + p.matcher("-3.33c").matches()); System.out.println("-3.33C " + p.matcher("-3.33C").matches()); System.out.println("===========正則內部忽略大小寫==========="); moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*(?i)[CF]"; p = Pattern.compile(moneyRegex); System.out.println("-3.33c " + p.matcher("-3.33c").matches()); System.out.println("-3.33C " + p.matcher("-3.33C").matches()); System.out.println("===========內部不忽略大小寫==========="); moneyRegex = "[+-]?(\\d)+(.(\\d)*)?(\\s)*[CF]"; p = Pattern.compile(moneyRegex); System.out.println("-3.33c " + p.matcher("-3.33c").matches()); System.out.println("-3.33C " + p.matcher("-3.33C").matches()); } }
===========API忽略大小寫===========
-3.33c true
-3.33C true
===========不忽略大小寫===========
-3.33c false
-3.33C true
===========正則內部忽略大小寫===========
-3.33c true
-3.33C true
===========內部不忽略大小寫===========
-3.33c false
-3.33C true
啟用注釋,開啟之后,正則表達式中的空格以及#號行將被忽略。
import java.util.regex.Pattern; public class ReFlags_COMMENTS { public static void main(String[] args) { System.out.println("===========API啟用注釋==========="); String comments = " (\\d)+#this is comments."; Pattern p = Pattern.compile(comments, Pattern.COMMENTS); System.out.println("1234 " + p.matcher("1234").matches()); System.out.println("===========不啟用注釋==========="); comments = " (\\d)+#this is comments."; p = Pattern.compile(comments); System.out.println("1234 " + p.matcher("1234").matches()); System.out.println("===========正則啟用注釋==========="); comments = "(?x) (\\d)+#this is comments."; p = Pattern.compile(comments); System.out.println("1234 " + p.matcher("1234").matches()); System.out.println("===========不啟用注釋==========="); comments = " (\\d)+#this is comments."; p = Pattern.compile(comments); System.out.println("1234 " + p.matcher("1234").matches()); } }
===========API啟用注釋===========
1234 true
===========不啟用注釋===========
1234 false
===========正則啟用注釋===========
1234 true
===========不啟用注釋===========
1234 false
可以看到,#號到行尾的注釋部分和前面的空白字符都被忽略了。正則表達式內置的啟用注釋為(?x)。
啟用dotall模式,一般情況下,點號(.)匹配任意字符,但不匹配換行符,啟用這個模式之后,點號還能匹配換行符。
import java.util.regex.Pattern; public class ReFlags_DOTALL { public static void main(String[] args) { System.out.println("===========API啟用DOTALL==========="); String dotall = "<xml>(.)*</xml>"; Pattern p = Pattern.compile(dotall, Pattern.DOTALL); System.out.println("<xml>\\r\\n</xml> " + p.matcher("<xml>\r\n</xml>").matches()); System.out.println("===========不啟用DOTALL==========="); dotall = "<xml>(.)*</xml>"; p = Pattern.compile(dotall); System.out.println("<xml>\\r\\n</xml> " + p.matcher("<xml>\r\n</xml>").matches()); System.out.println("===========正則啟用DOTALL==========="); dotall = "(?s)<xml>(.)*</xml>"; p = Pattern.compile(dotall); System.out.println("<xml>\\r\\n</xml> " + p.matcher("<xml>\r\n</xml>").matches()); System.out.println("===========不啟用DOTALL==========="); dotall = "<xml>(.)*</xml>"; p = Pattern.compile(dotall); System.out.println("<xml>\\r\\n</xml> " + p.matcher("<xml>\r\n</xml>").matches()); } }
===========API啟用DOTALL===========
<xml>\r\n</xml> true
===========不啟用DOTALL===========
<xml>\r\n</xml> false
===========正則啟用DOTALL===========
<xml>\r\n</xml> true
===========不啟用DOTALL===========
<xml>\r\n</xml> false
啟用這個模式之后,所有元字符、轉義字符都被看成普通的字符,不再具有其他意義。
import java.util.regex.Pattern; public class ReFlags_LITERAL { public static void main(String[] args) { System.out.println(Pattern.compile("\\d", Pattern.LITERAL).matcher("\\d").matches());// true System.out.println(Pattern.compile("\\d", Pattern.LITERAL).matcher("2").matches());// false System.out.println(Pattern.compile("(\\d)+", Pattern.LITERAL).matcher("1234").matches());// false System.out.println(Pattern.compile("(\\d)+").matcher("1234").matches());// true System.out.println(Pattern.compile("(\\d){2,3}", Pattern.LITERAL).matcher("(\\d){2,3}").matches());// true } }
考慮這個表達式:a.*b,它將會匹配最長的以a開始,以b結束的字符串。如果用它來搜索aabab的話,它會匹配整個字符串aabab。這被稱為貪婪匹配。
有時,我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉化為懶惰匹配模式,只要在它后面加上一個問號?。這樣.*?就意味著匹配任意數量的重復,但是在能使整個匹配成功的前提下使用最少的重復。
a.*?b匹配最短的,以a開始,以b結束的字符串。如果把它應用于aabab的話,它會匹配aab和ab。
public static void main(String[] args) { String str = "北京市(海淀區)(朝陽區)"; String paternStr = ".*(?=\\()"; Pattern pattern = Pattern.compile(paternStr); Matcher matcher = pattern.matcher(str); if (matcher.find()) { System.out.println(matcher.group(0)); } }
上述方法的輸出為:北京市(海淀區)
public static void main(String[] args) { String str = "北京市(海淀區)(朝陽區)"; String paternStr = ".*?(?=\\()"; Pattern pattern = Pattern.compile(paternStr); Matcher matcher = pattern.matcher(str); if (matcher.find()) { System.out.println(matcher.group(0)); } }
上述方法輸出:北京市
到此,相信大家對“Java正則表達式中Pattern類怎么用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。