Pattern 物件
July 2, 2022剖析、驗證規則表示式往往是最耗時間的階段,在頻繁使用某規則表示式的場合,若能重複使用剖析、驗證過後的規則表示式,對效率會有幫助。
建立Pattern
java.util.regex.Pattern
實例是規則表示式代表物件,Pattern
的建構式被標示為 private
,無法用 new
建構 Pattern
實例,必須透過 Pattern
的靜態方法 compile
,在剖析、驗證過規則表示式無誤後,compile
會傳回 Pattern
實例,之後就可以重用這個實例。例如:
var pattern = Pattern.compile(".*foo");
Pattern.compile
方法的另一版本,可以指定旗標(Flag),例如想不分大小寫比對 dog 文字,可以如下:
var pattern = Pattern.compile("dog", Pattern.CASE_INSENSITIVE);
指定旗標 Pattern.LITERAL
的話,字串撰寫規則表示式時,就不用迴避詮譯字元(不過 \
還是得迴避,以免與字串表示法衝突):
jshell> import java.util.regex.Pattern;
jshell> var pattern = Pattern.compile("+", Pattern.LITERAL);
pattern ==> +
jshell> pattern.split("Justin+Monica")
$1 ==> String[2] { "Justin", "Monica" }
函數式概念 API
Pattern
有個 splitAsStream
靜態方法,它傳回的是 Stream<String>
,適用於需要管線化、惰性操作的場合:
jshell> var regex = Pattern.compile("\\+");
regex ==> \+
jshell> var tokens = regex.splitAsStream("Justin+Monica+Irene");
tokens ==> java.util.stream.ReferencePipeline$Head@5a1c0542
jshell> tokens.filter(token -> token.indexOf('i') != -1).map(String::toUpperCase).forEach(out::println);
JUSTIN
MONICA
Pattern
實例可以藉由 asPredicate
轉為 Predicate
物件,在需要 Predicate
作為引數的場合時可以使用:
jshell> var regex = Pattern.compile("\\+");
regex ==> \+
jshell> var tokens = regex.splitAsStream("Justin+Monica+irene");
tokens ==> java.util.stream.ReferencePipeline$Head@2833cc44
jshell> tokens.filter(Pattern.compile("\\p{Upper}+").asPredicate()).forEach(System.out::println);
Justin
Monica
嵌入旗標表示法
也可以在規則表示式使用嵌入旗標表示法(Embedded Flag Expression)。例如 Pattern.CASE_INSENSITIVE
等效的嵌入旗標表示法為 (?i)
,以下片段效果等同上例:
var pattern = Pattern.compile("(?i)dog");
若想對特定分組嵌入旗標,可以使用 (?i:dog)
這樣的語法;並非全部的常數旗標都有對應的嵌入式表示法,底下列出有對應的旗標:
Pattern.CASE_INSENSITIVE
:(?i)
Pattern.COMMENTS
:(?x)
Pattern.MULTILINE
:(?m)
Pattern.DOTALL
:(?s)
Pattern.UNIX_LINES
:(?d)
Pattern.UNICODE_CASE
:(?u)
Pattern.UNICODE_CHARACTER_CLASS
:(?U)
Pattern.COMMENTS
允許在規則表示式以 #
嵌入註解;Pattern.MULTILINE
啟用多行文字模式(影響了 ^
、$
的行為,換行字元後、前會被視為行首、行尾);預設情況下.不匹配換行字元,可設置 Pattern.DOTALL
來匹配換行字元;Pattern.UNIX_LINES
啟用後,只有 \n
才被視為換行字元,作為 .
、^
與 $
判斷依據。
Pattern.UNICODE_CASE
、Pattern.UNICODE_CHARACTER_CLASS
與規則表示式 Unicode 支援有關,稍後再來說明。
規則表示式本身可讀性差、除錯不易,若因規則表示式有誤而導致 compile
呼叫失敗,會拋出 java.util.regex.PatternSyntaxException
,可以使用 getDescription
取得錯誤說明、getIndex
取得錯誤索引、getPattern
取得錯誤的規則表示式,getMessage
會以多行顯示錯誤的索引、描述等綜合訊息。