Java 沒有為規則表示式制定專用的實字(Literal)撰寫方式,也沒有像 Python 的原始字串特性,因此在 Java 中撰寫規則表示式,實際上是蠻麻煩的。
若有個 Java 字串是 "Justin+Monica+Irene"
, 想使用 split
方法依 +
切割,要使用的規則表示式是 \+
,要將 \+
放至 ""
之間時,按照 Java 字串的規定,必須轉義 \+
的 \
,所以必須撰寫為 "\\+"
。
jshell> "Justin+Monica+Irene".split("\\+");
$1 ==> String[3] { "Justin", "Monica", "Irene" }
類似地,如果有個 Java 字串是 "Justin||Monica||Irene"
,想使用 split
方法依 ||
切割,要使用的規則表示式是 \|\|
,要將 \|\|
放至 ""
之間時,按照 Java 字串規定必須忽略 \|
的 \
,就必須撰寫為 "\\|\\|"
。例如:
jshell> "Justin||Monica||Irene".split("\\|\\|");
$2 ==> String[3] { "Justin", "Monica", "Irene" }
如果有個字串是 "Justin\\Monica\\Irene"
,也就是原始文字是 Justin\Monica\Irene 以 Java 字串表示,若想使用 split
方法依 \
切割,要使用的規則表示式是 \\
,那就得如下撰寫:
jshell> "Justin\\Monica\\Irene".split("\\\\");
$3 ==> String[3] { "Justin", "Monica", "Irene" }
這麼撰寫當然非常的麻煩,java.util.regex.Pattern
提供了 quote
靜態方法,可以幫你對規則表示式的詮譯字元進行轉義:
jshell> import static java.util.regex.Pattern.quote;
jshell> "Justin+Monica+Irene".split(quote("+"));
$4 ==> String[3] { "Justin", "Monica", "Irene" }
jshell> "Justin||Monica||Irene".split(quote("||"));
$5 ==> String[3] { "Justin", "Monica", "Irene" }
jshell> "Justin\\Monica\\Irene".split(quote("\\"));
$6 ==> String[3] { "Justin", "Monica", "Irene" }
quote
方法實際上會在指定的字串前後加上 \Q
與 \E
,這個表示法在 Java 中用來表示 \Q
與 \E
之間的全部字元,都不當成詮譯字元。
jshell> Pattern.quote(".");
$7 ==> "\\Q.\\E"
如果要將字串編譯為 Pattern
物件,可以指定旗標 Pattern.LITERAL
,這樣會將全部的詮譯字元當成一般字元來比對。
相對地,如果想要取代字串,打算使用 $
之類的符號,也必須進行轉義:
jshell> "java.exe".replaceFirst(quote("."), "\\$");
$8 ==> "java$exe"
因為 $
用來作為分組參考的前置字元,如果不轉義的話會發生例外:
jshell> "java.exe".replaceFirst(quote("."), "$");
| Exception java.lang.IllegalArgumentException: Illegal group reference: group index is missing
| at Matcher.appendExpandedReplacement (Matcher.java:1030)
| at Matcher.appendReplacement (Matcher.java:998)
| at Matcher.replaceFirst (Matcher.java:1408)
| at String.replaceFirst (String.java:2081)
|
對於這類情況,可以使用 java.util.regex.Matcher
提供的 quoteReplacement
靜態方法:
jshell> import static java.util.regex.Matcher.quoteReplacement;
jshell> "java.exe".replaceFirst(quote("."), quoteReplacement("$"));
$9 ==> "java$exe
不過,遇到 \d
、\s
等預定義字元類,也只能乖乖轉義了,所幸,現代 IDE 將文字貼到 ""
裏頭時,會自動為 \
加上轉義。例如:
這些方式搭配一下,在 Java 中撰寫規則表示式時,應該就可以省不少功夫吧!…XD
String
上可以使用規則表示式的方法,在方才已經看過 split
與 replaceFirst
,另外還有 replaceAll
方法。注意到 replace
方法,是不支援規則表示式的:
String replace(char oldChar, char newChar)
matches
方法用來測試全字串是否符合規則表示式:
jshell> "0970-168168".matches("\\d{4}-\\d{6}");
$10 ==> true
jshell> "Phone: 0970-168168".matches("\\d{4}-\\d{6}");
$11 ==> false