關於正則表達式的小筆記
1.1概述
正則表達式是一種強大而靈活的文本處理工具。使用正則表達式,我們能夠以編程的方式,構造複雜的文本模式,並對輸入的字符串進行搜索。一旦找到了相匹配的部分,就能隨心所欲進行處理。
在java語言中的正則表達式對反斜槓\有着與其它語言不同的處理。其它語言中,\\表示“想要在正則表達式中插入一個普通的反斜線,沒有任何特殊的意義”;而在java中,\\表示“要插入一個正則表達式的反斜線,因此其後的字符具有特殊的意義。”如:表示一位數字,用\\d表示。
1.2創建正則表達式
表1-1
字符 |
|
B |
指定字符B |
\xhh |
十六進制值爲oxhh的字符 |
\uhhhh |
十六進制表示爲oxhhhh的Unicode |
\t |
製表符Tab |
\n |
換行符 |
\r |
回車 |
\f |
換頁 |
\e |
轉義(Escape) |
只有學會使用字符類之後,正則表達式的威力才能真正顯現出來。以下是一些創建字符類的典型方式。
表1-2
字符 |
|
. |
任意字符 |
[abc] |
包含a、b和c的任意字符(和a|b|c作用相同) |
[^abc] |
除了a、b和c之外的任何字符(否定) |
[a-zA-Z] |
從a到z或從A到Z的任何字符(範圍) |
[abc[hij]] |
任意a、b、c、h、i和j字符(和a|b|c|h|i|j作用相同) |
[a-z&&[hij]] |
任意h、i或j(相交) |
\s |
空白符(空格、tab、換行、換頁和回車) |
\S |
非空白符([^\S]) |
\d |
數字[0-9] |
\D |
非數字[^0-9] |
\w |
詞字符[a-zA-Z0-9] |
\W |
非詞字符[^\w] |
表1-3
邏輯操作符 |
|
XY |
Y跟在X後面 |
X|Y |
X或Y |
(X) |
捕獲組,可以在表達式中用\i引用第i個捕獲組 |
表1-4
邊界匹配符 |
|
^ |
一行的起始 |
$ |
一行的結束 |
\b |
詞的邊界 |
\B |
非詞的邊界 |
\G |
前一個匹配的結束 |
舉個例子:
public class Demo{
public static void main(String[] args){
for(String str:new String[]{"Rudolph","[rR]udolph","[rR][aeiou][a-z]ol.*","R.*"}){
System.out.println("Rudolph".matches(str));
}
}
}
[rR]udolph:r或R開頭;
[rR][aeiou][a-z]ol.*:r或R開頭,第二個字母[aeiou]中一個,第三個[a-z]中一個,後接ol,最後爲任意字符;
R.*:R打頭的任意字符串。
1.3量詞
量詞描述了一個模式吸收輸入文本的方式:
- 貪婪型:量詞總是貪婪的,除非有其他的選項被設置。貪婪表達式會爲所有可能的模式發現儘可能多的匹配。假如現有模式僅能匹配第一個可能的字符組,如果它是貪婪的,那麼它就會繼續匹配下去。
- 勉強型:用問號來指定,這個量詞匹配滿足模式所需的最少字符數。所以也稱爲懶惰的、最少匹配的和非貪婪的。
- 佔有型:這種類型只有在java語言中才可用,當正則表達式被應用於字符串時,它會產生相當多的狀態,以便在匹配失敗時可以回溯。常用於防止正則表達式失控。
貪婪型 |
勉強型 |
佔有性 |
匹配 |
X? |
X?? |
X?+ |
一個或零個X |
X* |
X*? |
X*+ |
零個或多個X |
X+ |
X+? |
X++ |
一個或多個X |
X{n} |
X{n}? |
X{n}+ |
X恰好出現n次 |
X{n,} |
X{n,}? |
X{n,}+ |
X至少出現n次 |
X{n,m} |
X{n,m}? |
X{n,m}+ |
X至少出現n次,且不超過m次 |
注:這裏的表達式X,要使用圓括號括起來,如(abc)+。
1.4Pattern和Matcher
雖然String類中也能使用正則表達式,但其功能有限,所以更願意使用功能強大的regex包下的Pattern.complie()方法來編譯正則表達式。
- 會更根據正則表達式生成一個Pattern對象;
- 然後將要檢索的字符串傳入Pattern對象的matcher()方法;
- matcher()方法會生成一個Matcher對象。
public class Test{
public static void main(String[] args){
for(String str : args){
Pattern p = Pattern.compile(str);
Matcher m = p.matcher(args[0]);
while(m.find()){
m.group();
m.start();
m.end();
}
}
}
}
1.4.1 find()
Matcher.find()方法可用來在Test中查找多個匹配,find()對字符串進行匹配,匹配到的字符串可以在任何位置。
find(int i) 重置匹配器,然後嘗試查找匹配該模式、並以指定索引i開始匹配。如下代碼:
@Test
public void run(){
String s = "hello world";
Pattern p = Pattern.compile("\\w+");
Matcher m = p.matcher(s);
int i = 0;
while(m.find(i)){
System.out.println(m.group());
i++;
}
}
/*output
hello
ello
llo
lo
o
world
world
orld
rld
ld
d
*/
1.4.2 組(groups)
Matcher對象提供了一系列方法,用以獲取與組相關的信息:
- l int groupCount()返回該匹配器的模式中分組數目;
- l String group(int group)返回在以前匹配操作期間由給定組捕獲的輸入子序列。
- l int start()返回以前匹配的起始位置的索引。
- l int start(int group)返回在以前的匹配操作期間,由給定組所捕獲的子序列的起始索引。
- l int end()返回最後匹配字符的索引加一的值。
- l int end(int group)返回在前一次匹配操作中,尋找到組的最後一個字符索引加一的值。
- l boolean matches()只有在完全匹配正則表達式纔會返回true。
- l boolean lookingAt()嘗試將從區域開頭開始的輸入序列與該模式匹配,只要輸入的第一部分匹配就返回true。
1.5split()
split()方法將輸入字符串斷開成字符串對象數組,斷開邊界由下列正則表達式確定:
- l String[]split(CharSequence input)圍繞此模式的匹配拆分給定輸入序列。
- l String[]split(CharSequence input, int limit)圍繞此模式的匹配拆分給定輸入序列。注:limit可限定通過分割符分割後的字符串數量。
1.6替換操作
- l String replaceAll(Stringreplacement)替換模式與給定替換字符串相匹配的輸入序列的每個子序列。
- l String replaceFirst(Stringreplacement)替換模式與給定替換字符串匹配的輸入序列的第一個子序列。
- l Matcher appendReplacement(StringBuffersb, String replacement)執行漸進式的替換。
- l StringBufferappendTail(StringBuffer sb)在執行一次或多次appendReplacement()之後,此方法可以將匹配完後剩下的部分複製到sb中。
1.7reset()
Matcher reset()方法可以重置匹配器,將現有的Matcher對象應用於一個新的字符序列。
1.8Pattern標記
static Pattern compile(String regex, int flags)將給定的正則表達式編譯到具有給定標誌的模式中。
編譯標記 |
效果 |
Pattern.CANON_EQ |
兩個字符當且僅當它們的完全規範分解相匹配時,就認爲它們是匹配的。例如,如果我們指定這個標記,表達式a\u030A就會匹配字符串?。在默認的情況下,匹配不考慮規範的等價性。 |
Pattern.CASE_INSENSITIVE(?i) |
默認情況下,大小寫不敏感的匹配假定只有US-ASCII字符集中的字符才能進行。這個標記允許模式匹配不必考慮大小寫(大寫或小寫)。通過指定UNICODE_CASE標記及結合此標記。基於Unicode的大小寫不滿乾的匹配就可以開啓了。 |
Pattern.COMMENTS(?x) |
在這種模式下,空格符將被忽略掉,並且以#開始直到行末的註釋也會被忽略掉。通過嵌入的標記表達式也可以開啓Unix的行模式X。 |
Pattern.DOTALL(?s) |
在dotall模式中,表達式"." 匹配所有字符,包括終結符。默認情況下,”." 表達式不匹配行終結符。 |
Pattern.MULTILINE(?m) |
在多行模式下,表達式^和$分別匹配一行的開始和結束。^還匹配輸入字符串的開始,而$還匹配輸入字符串的結尾。默認情況下,這些表達式僅匹配輸入的完整字符串的開始和結束。 |
Pattern.UNICODE_CASE(?u) |
當指定這個標記, 並且開啓CASE_INSENSITIVE時,大小寫不敏感的匹配將按照與Unicode標準相一致的方式進行。默認情況下,大小寫不敏感的匹配假定只能在US-ASCII 字符集中 |
Pattern.UNIX_LINES(?d) |
在這種模式下,在., ^和$行爲中, 只識別行終結符\n |
以上表格摘自《java編程思想》