Android:Java正則表達式

元字符

代碼 說明
. 匹配除換行符以外的任意字符
\w 匹配字母或數字或下劃線或漢字
\s 匹配任意的空白符
\d 匹配數字
^ 匹配字符串的開始
$ 匹配字符串的結束
\b 匹配字符串的結束

重復

代碼/語法 說明
* 重復零次或更多次
+ 重復一次或更多次
? 重復零次或一次
{n} 重復n次
{n,} 重復n次或更多次
{n,m} 重復n到m次

字符類

想查找數字忽洛,字母或數字,空白是很簡單的,因為已經有了對應這些字符集合的元字符杈曲,但是如果你想匹配沒有預定義元字符的字符集合(比如元音字母a,e,i,o,u),應該怎么辦捉超?
很簡單资溃,你只需要在方括號里列出它們就行了大莫,像[aeiou]就匹配任何一個英文元音字母勿侯,[.?!]匹配標點符號(.或?或!)拓瞪。
我們也可以輕松地指定一個字符范圍,像[0-9]代表的含意與\d就是完全一致的:一位數字罐监;同理[a-z0-9A-Z_]也完全等同于\w(如果只考慮英文的話)吴藻。

分枝條件

用|把不同的規(guī)則分別表達。
如:0\d{2}-\d{8}|0\d{3}-\d{7}這個表達式能匹配兩種以連字號分隔的電話號碼:一種是三位區(qū)號弓柱,8位本地號(如010-12345678)沟堡,一種是4位區(qū)號,7位本地號(0376-2233445)矢空。

反義

代碼/語法 說明
\W 匹配任意不是字母航罗,數字,下劃線屁药,漢字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非數字的字符
\B 匹配不是單詞開頭或結束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou這幾個字母以外的任意字符

分組

重復單個字符直接在字符后面加上限定符就行了粥血,但如果想要重復多個字符又該怎么辦?你可以用小括號來指定子表達式(也叫做分組),然后你就可以指定這個子表達式的重復次數了复亏,你也可以對子表達式進行其它一些操作趾娃。
使用小括號指定一個子表達式后,匹配這個子表達式的文本(也就是此分組捕獲的內容)可以在表達式或其它程序中作進一步的處理缔御。捕獲組可以通過從左到右計算其開括號來編號抬闷。例如,在表達式 ((A)(B(C))) 中耕突,存在四個這樣的組:

  1. ((A)(B(C)))
  2. (A)
  3. (B(C))
  4. (C)

組零始終代表整個表達式笤成。

之所以這樣命名捕獲組是因為在匹配中,保存了與這些組匹配的輸入序列的每個子序列眷茁。捕獲的子序列稍后可以通過 Back 引用在表達式中使用炕泳,也可以在匹配操作完成后從匹配器獲取。

與組關聯的捕獲輸入始終是與組最近匹配的子序列上祈。如果由于量化的緣故再次計算了組培遵,則在第二次計算失敗時將保留其以前捕獲的值(如果有的話)例如,將字符串 "aba" 與表達式 (a(b)?)+ 相匹配雇逞,會將第二組設置為 "b"荤懂。在每個匹配的開頭,所有捕獲的輸入都會被丟棄塘砸。

以 (?) 開頭的組是純的非捕獲 組,它不捕獲文本晤锥,也不針對組合計進行計數掉蔬。

后向引用用于重復搜索前面某個分組匹配的文本。例如:
\b(\w+)\b\s+\1\b可以用來匹配重復的單詞矾瘾,像go go, 或者kitty kitty女轿。

也可以自己指定子表達式的組名。要指定一個子表達式的組名壕翩,請使用這樣的語法:(?<Word>\w+)(或者把尖括號換成'也行:(?'Word'\w+)),這樣就把\w+的組名指定為Word了蛉迹。要反向引用這個分組捕獲的內容,你可以使用\k<Word>,所以上一個例子也可以寫成這樣:\b(?<Word>\w+)\b\s+\k<Word>\b放妈。

零寬斷言

(?=exp)也叫零寬度正預測先行斷言北救,它斷言被匹配的字符串以表達式exp結尾但除了結尾以外的部分。比如\b\w+(?=ing\b)芜抒,匹配以ing結尾的單詞的前面部分(除了ing以外的部分)珍策,如查找I'm singing while you're dancing.時,它會匹配sing和danc宅倒。
(?<=exp)也叫零寬度正回顧后發(fā)斷言攘宙,它斷言自身出現的位置的前面能匹配表達式exp。比如(?<=\bre)\w+\b會匹配以re開頭的單詞的后半部分(除了re以外的部分),例如在查找reading a book時蹭劈,它匹配ading疗绣。

代碼/語法 說明
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置

注釋

小括號的另一種用途是通過語法(?#comment)來包含注釋。例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d \d?(?#0-199)铺韧。

貪婪與懶惰

語法 說明
*? 重復任意次多矮,但盡可能少重復
+? 重復1次或更多次,但盡可能少重復
?? 重復0次或1次祟蚀,但盡可能少重復
{n,m}? 重復n到m次工窍,但盡可能少重復
{n,}? 重復n次以上,但盡可能少重復

當正則表達式中包含能接受重復的限定符時前酿,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可
能多的字符患雏。考慮這個表達式:a.*b罢维,它將會匹配最長的以a開始淹仑,以b結束的字符串。如果用它來搜索aabab的
話肺孵,它會匹配整個字符串aabab匀借。這被稱為貪婪匹配。
有時平窘,我們更需要懶惰匹配吓肋,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉化為懶惰匹配模式瑰艘,
只要在它后面加上一個問號?是鬼。這樣.*?就意味著匹配任意數量的重復,但是在能使整個匹配成功的前提下使用
最少的重復∽闲拢現在看看懶惰版的例子吧:
a.*?b匹配最短的均蜜,以a開始,以b結束的字符串芒率。如果把它應用于aabab的話囤耳,它會匹配aab(第一到第三個字
符)和ab(第四到第五個字符)。

POSIX 字符類(僅 US-ASCII)

語法 說明
\p{Lower} 小寫字母字符:[a-z]
\p{Upper} 大寫字母字符:[A-Z]
\p{ASCII} 所有 ASCII:[\x00-\x7F]
\p{Alpha} 字母字符:[\p{Lower}\p{Upper}]
\p{Digit} 十進制數字:[0-9]
\p{Alnum} 字母數字字符:[\p{Alpha}\p{Digit}]
\p{Punct} 標點符號:`!"#$%&'()*+,-./:;<=>?@[]^_{ }~`
\p{Graph} 可見字符:[\p{Alnum}\p{Punct}]
\p{Print} 可打印字符:[\p{Graph}\x20]
\p{Blank} 空格或制表符:[ \t]
\p{Cntrl} 控制字符:[\x00-\x1F\x7F]
\p{XDigit} 十六進制數字:[0-9a-fA-F]
\p{Space} 空白字符:[ \t\n\x0B\f\r]

引用

語法 說明
\ Nothing偶芍,但是引用以下字符
\Q Nothing充择,但是引用所有字符,直到 \E
\E Nothing腋寨,但是結束從 \Q 開始的引用

如:\Q\w+\E表示字符串\w+而不是正則中的單詞字符:[a-zA-Z_0-9]聪铺。

其他

語法 說明
\xhh 十六進制值為0xhh的字符
\uhhhh 十六進制表示為0xhhhh的Unicode字符
\t 制表符Tab
\n 換行符
\r 回車
\f 換頁
\e 轉義(Escape)

處理選項

上面介紹了幾個選項如忽略大小寫,處理多行等萄窜,這些選項能用來改變處理正則表達式的方式铃剔。下面是Java中常用的正則表達式選項:

名稱 說明
CASE_INSENSITIVE 匹配時區(qū)分大小寫
MULTILINE 更改^$的含義撒桨,使它們分別在任意一行的行首和行尾匹配,而不僅僅在整個字符串的開頭和結尾匹配键兜。(在此模式下,$的精確含意是:匹配\n之前的位置以及字符串結束前的位置.)
DOTALL 在 dotall 模式中凤类,表達式 . 可以匹配任何字符,包括行結束符普气。默認情況下谜疤,此表達式不匹配行結束符。
UNICODE_CASE 指定此標志后现诀,由 CASE_INSENSITIVE 標志啟用時夷磕,不區(qū)分大小寫的匹配將以符合 Unicode Standard 的方式完成。默認情況下仔沿,不區(qū)分大小寫的匹配假定僅匹配 US-ASCII 字符集中的字符坐桩。通過嵌入式標志表達式 (?u) 也可以啟用 Unicode 感知的大小寫折疊。指定此標志可能對性能產生影響封锉。
CANON_EQ 啟用規(guī)范等價绵跷。指定此標志后,當且僅當其完整規(guī)范分解匹配時成福,兩個字符才可視為匹配碾局。例如,當指定此標志時奴艾,表達式 "a\u030A" 將與字符串 "\u00E5" 匹配净当。默認情況下,匹配不考慮采用規(guī)范等價蕴潦。不存在可以啟用規(guī)范等價的嵌入式標志字符蚯瞧。指定此標志可能對性能產生影響。
UNIX_LINES 啟用 Unix 行模式品擎。在此模式中,.备徐、^ 和 $ 的行為中僅識別 '\n' 行結束符萄传。通過嵌入式標志表達式 (?d) 也可以啟用 Unix 行模式。
LITERAL 指定此標志后蜜猾,指定模式的輸入字符串就會作為字面值字符序列來對待秀菱。輸入序列中的元字符或轉義序列不具有任何特殊意義。標志 CASE_INSENSITIVE 和 UNICODE_CASE 在與此標志一起使用時將對匹配產生影響蹭睡。其他標志都變得多余了衍菱。不存在可以啟用字面值解析的嵌入式標志字符。
UNICODE_CHARACTER_CLASS
COMMENTS 模式中允許空白和注釋肩豁。此模式將忽略空白和在結束行之前以 # 開頭的嵌入式注釋脊串。通過嵌入式標志表達式 (?x) 也可以啟用注釋模式辫呻。

JAVA

基本用法

Pattern pattern = Pattern.compile("\\ba\\w*\\b");
Matcher matcher = pattern.matcher("abcdab cccabcd aaacd");
int index = 0;
while (matcher.find()) {
    String res = matcher.group();
    System.out.println(index + ":" + res);
    index++;
}

\\ba\\w*\\b表示匹配以字母a為開頭的單詞。
Pattern.compile(regex)表示將給定的正則表達式編譯到具有給定標志的模式中琼锋。
matcher(str)創(chuàng)建匹配給定輸入與此模式的匹配器放闺。
mather.find()嘗試查找與該模式匹配的輸入序列的下一個子序列。
此方法從匹配器區(qū)域的開頭開始缕坎,如果該方法的前一次調用成功了并且從那時開始匹配器沒有被重置怖侦,則從以前匹配操作沒有匹配的第一個字符開始。
如果匹配成功谜叹,則可以通過 start匾寝、end 和 group 方法獲取更多信息。
group() 返回由以前匹配操作所匹配的輸入子序列荷腊。
打印結果:

image

不同

從上例中可以看出艳悔,Java中的正則表達式與之前所說不一致(多了一個\),在其他語言中\\表示我想在正則表達式中插入一個普通的反斜線停局,請不要給它任何特殊的意義很钓,而在Java中,\\的意思是我想要插入一個正則表達式的反斜線董栽,所以其后的字符具有特殊的意義码倦。

如果想表示數字,則是\\d锭碳。如果要插入普通的反斜線袁稽,則是\\\\

String

String類中有幾種方法可以使用正則表達式:

方法 返回類型 功能 示例
matches() boolean 告知此字符串是否匹配給定的正則表達式擒抛。 "-1234".matches("^-?\\d+$") => true
replaceAll(String regex, String replacement) String 使用給定的 replacement 替換此字符串所有匹配給定的正則表達式的子字符串推汽。 "a1b2c3".replaceAll("[a-zA-z]", "") => 123
replaceFirst(String regex, String replacement) String 使用給定的 replacement 替換此字符串匹配給定的正則表達式的第一個子字符串。 "Hello World! Hello Everyone!".replaceFirst("\\s", "") => HelloWorld! Hello Everyone!
split(String regex) String[] 根據給定正則表達式的匹配拆分此字符串歧沪。 "boo:and:foo".split(":") => { "boo", "and", "foo" }
split(String regex, int limit) String[] 根據給定正則表達式的匹配拆分此字符串歹撒。 "boo:and:foo".split(":", 5) => { "boo", "and", "foo" }

split(String regex, int limit)方法中l(wèi)imit 參數控制模式應用的次數,因此影響所得數組的長度诊胞。如果該限制 n 大于 0暖夭,則模式將被最多應用 n - 1 次,數組的長度將不會大于 n撵孤,而且數組的最后一項將包含所有超出最后匹配的定界符的輸入迈着。如果 n 為非正,那么模式將被應用盡可能多的次數邪码,而且數組可以是任何長度裕菠。如果 n 為 0,那么模式將被應用盡可能多的次數闭专,數組可以是任何長度奴潘,并且結尾空字符串將被丟棄旧烧。

例如,字符串 "boo:and:foo" 使用這些參數可生成以下結果:

Regex Limit 結果
: 2 { "boo", "and:foo" }
: 5 { "boo", "and", "foo" }
: -2 { "boo", "and", "foo" }
o 5 { "b", "", ":and:f", "", "" }
o -2 { "b", "", ":and:f", "", "" }
o 0 { "b", "", ":and:f" }

調用此方法的 str.split(regex, n) 形式與以下表達式產生的結果完全相同:Pattern.compile(regex).split(str, n)

java.util.regex

在regex包中萤彩,包括了兩個類粪滤,Pattern(模式類)和Matcher(匹配器類)。Pattern類是用來表達和陳述所要搜索模式的對象雀扶,Matcher類是真正影響搜索的對象杖小。另加一個新的例外類,PatternSyntaxException愚墓,當遇到不合法的搜索模式時予权,會拋出例外。

Pattern

  • 簡介
    正則表達式的編譯表示形式浪册。

    指定為字符串的正則表達式必須首先被編譯為此類的實例扫腺。然后,可將得到的模式用于創(chuàng)建 Matcher 對象村象,依照正則表達式笆环,該對象可以與任意字符序列匹配。執(zhí)行匹配所涉及的所有狀態(tài)都駐留在匹配器中厚者,所以多個匹配器可以共享同一模式躁劣。

    因此,典型的調用順序是

     Pattern p = Pattern.compile("a*b");
     Matcher m = p.matcher("aaaaab");
     boolean b = m.matches();
    
    

    在僅使用一次正則表達式時库菲,可以方便地通過此類定義 matches 方法账忘。此方法編譯表達式并在單個調用中將輸入序列與其匹配。語句

     boolean b = Pattern.matches("a*b", "aaaaab");
    
    

    等效于上面的三個語句熙宇,盡管對于重復的匹配而言它效率不高鳖擒,因為它不允許重用已編譯的模式。
    此類的實例是不可變的烫止,可供多個并發(fā)線程安全使用蒋荚。Matcher 類的實例用于此目的則不安全。

  • 常用方法

Pattern類中最重要的方法便是compilematcher馆蠕,上面已經給出示例圆裕。下面看看其他方法:

方法 返回類型 功能 示例
flags() int 返回此模式的匹配標志。 Pattern.compile("\\w*", Pattern.MULTILINE).flags() => 8
pattern() String 返回在其中編譯過此模式的正則表達式荆几。 Pattern.compile("\\w*").pattern() => \w*
static quote(String s) String 返回指定 String 的字面值模式 String。 Pattern.quote("\\w+") => \Q\w+\E

Matcher

  • 簡介

通過解釋 Pattern 對 character sequence 執(zhí)行匹配操作的引擎赊时。

通過調用模式的 matcher 方法從模式創(chuàng)建匹配器吨铸。創(chuàng)建匹配器后,可以使用它執(zhí)行三種不同的匹配操作:

  • matches 方法嘗試將整個輸入序列與該模式匹配祖秒。

  • lookingAt 嘗試將輸入序列從頭開始與該模式匹配诞吱。

  • find 方法掃描輸入序列以查找與該模式匹配的下一個子序列舟奠。

每個方法都返回一個表示成功或失敗的布爾值。通過查詢匹配器的狀態(tài)可以獲取關于成功匹配的更多信息房维。

匹配器在其輸入的子集(稱為區(qū)域)中查找匹配項沼瘫。默認情況下,此區(qū)域包含全部的匹配器輸入咙俩」⑵荩可通過 region 方法修改區(qū)域,通過 regionStart 和 regionEnd 方法查詢區(qū)域阿趁。區(qū)域邊界與某些模式構造交互的方式是可以更改的膜蛔。

此類還定義使用新字符串替換匹配子序列的方法,需要時脖阵,可以從匹配結果計算出新字符串的內容皂股。可以先后使用 appendReplacement 和 appendTail 方法將結果收集到現有的字符串緩沖區(qū)命黔,或者使用更加便捷的 replaceAll 方法創(chuàng)建一個可以在其中替換輸入序列中每個匹配子序列的字符串呜呐。

匹配器的顯式狀態(tài)包括最近成功匹配的開始和結束索引。它還包括模式中每個捕獲組捕獲的輸入子序列的開始和結束索引以及該子序列的總數悍募。出于方便的考慮蘑辑,還提供了以字符串的形式返回這些已捕獲子序列的方法。

匹配器的顯式狀態(tài)最初是未定義的搜立;在成功匹配導致 IllegalStateException 拋出之前嘗試查詢其中的任何部分以躯。每個匹配操作都將重新計算匹配器的顯式狀態(tài)。

匹配器的隱式狀態(tài)包括輸入字符序列和添加位置啄踊,添加位置最初是零忧设,然后由 appendReplacement 方法更新。

可以通過調用匹配器的 reset() 方法來顯式重置匹配器颠通,如果需要新輸入序列址晕,則調用其 reset(CharSequence) 方法。重置匹配器將放棄其顯式狀態(tài)信息并將添加位置設置為零顿锰。

此類的實例用于多個并發(fā)線程是不安全的谨垃。

  • 常用方法

matches()
表示字符串完全符合給出的正則表達式所表示的范圍。只要有一個字符不匹配則返回false硼控。如:

Pattern.matches("[a-z]", "aAbBcC")

返回false刘陶,因為正則表達式表示的范圍不包含大寫字母。

find()
find()嘗試查找與該模式匹配的輸入序列的下一個子序列牢撼。
此方法從匹配器區(qū)域的開頭開始匙隔,如果該方法的前一次調用成功了并且從那時開始匹配器沒有被重置,則從以前匹配操作沒有匹配的第一個字符開始熏版。
如果匹配成功纷责,則可以通過 start捍掺、end 和 group 方法獲取更多信息。

    Pattern pattern = Pattern.compile("[a-z]");
    Matcher matcher = pattern.matcher("aAbBcC");
    matcher.find();

返回true再膳,因為可以匹配到小寫字母挺勿。

需要注意的是在執(zhí)行find()方法時,其內部指針會跟著變動喂柒,比如第一次調用完畢不瓶,此時的matcher.start()為0,因為第一個字母就匹配上了胳喷,而matcher.end()則返回2湃番,因為它返回的是最后不匹配(A)的位置的下一個索引,因此可以通過如下方法看到指針移動軌跡:

        Pattern p = Pattern.compile("\\d{3,5}");
        String s = "123-34345-234-00";
        while (m.find()) {
            System.out.println(m.start() + "-" + m.end());
        }

打印結果:


image

可以看到吭露,find方法比較實誠吠撮,善始善終,但我們有時候需要人工插手而不總是從頭到尾來一遍讲竿,這就涉及到find方法的另一個多態(tài)形式了泥兰。

find(int start)
從指定位置開始匹配,使用此方法模擬find():

        int index = 0;
        while (m.find(index)) {
            System.out.println(m.start() + "-" + m.end());
            index = m.end();
        }

lookingAt()
此方法總是從頭開始匹配题禀,無論是否匹配上均立即返回相應結果鞋诗,并且不再繼續(xù)匹配,語言乏力迈嘹,此處使用find方法模擬:

    public static void main(String[] args) throws Exception {
        Pattern p = Pattern.compile("\\d{3,5}");
        String s = "123-34345-234-00";
        Matcher m = p.matcher(s);

        System.out.println(cosplayMethodLookingAt(m));
        System.out.println(cosplayMethodLookingAt(m));
        System.out.println(cosplayMethodLookingAt(m));
        System.out.println(cosplayMethodLookingAt(m));
    }

    private static boolean cosplayMethodLookingAt(Matcher m) {
        boolean res = m.find() && m.start() == 0;
        m.reset();
        return res;
    }

顯示效果與lookingAt方法相同削彬,但內部實現不一樣:

    public static void main(String[] args) throws Exception {
        Pattern p = Pattern.compile("\\d{3,5}");
        String s = "123-34345-234-00";
        Matcher m = p.matcher(s);

        m.find();
        m.lookingAt();
        m.find();
        // 4
        System.out.println(m.start());
        cosplayMethodLookingAt(m);
        m.find();
        System.out.println(m.start());
    }

    private static boolean cosplayMethodLookingAt(Matcher m) {
        boolean res = m.find() && m.start() == 0;
        m.reset();
        return res;
    }

打印結果:


image

由此可見,lookingAt方法并不會重置匹配使用的內部指針秀仲。

appendReplacement
public Matcher appendReplacement(StringBuffer sb, String replacement)

實現非終端添加和替換步驟融痛。
此方法執(zhí)行以下操作:

它從添加位置開始在輸入序列讀取字符,并將其添加到給定字符串緩沖區(qū)神僵。在讀取以前匹配之前的最后字符(即位于索引 start() - 1 處的字符)之后雁刷,它就會停止。

它將給定替換字符串添加到字符串緩沖區(qū)保礼。

它將此匹配器的添加位置設置為最后匹配位置的索引加 1沛励,即 end()。

替換字符串可能包含到以前匹配期間所捕獲的子序列的引用:<nobr aria-hidden="true" style="margin: 0px; padding: 0px; transition: none 0s ease 0s; border: 0px; max-width: none; max-height: none; min-width: 0px; min-height: 0px; vertical-align: 0px; line-height: normal; text-decoration: none; white-space: nowrap !important;">g每次出現時炮障,都將被group(g)的計算結果替換目派。</nobr><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>g</mi><mrow class="MJX-TeXAtom-ORD"><mo>每</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>次</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>出</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>現</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>時</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>,</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>都</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>將</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>被</mo></mrow><mi>g</mi><mi>r</mi><mi>o</mi><mi>u</mi><mi>p</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">)</mo><mrow class="MJX-TeXAtom-ORD"><mo>的</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>計</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>算</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>結</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>果</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>替</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>換</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>胁赢。</mo></mrow></math> 之后的第一個數始終被視為組引用的一部分址貌。如果后續(xù)的數可以形成合法組引用,則將被合并到 g 中。只有數字 '0' 到 '9' 被視為組引用的可能組件练对。例如,如果第二個組匹配字符串 "foo"吹害,則傳遞替換字符串 "<nobr aria-hidden="true" style="margin: 0px; padding: 0px; transition: none 0s ease 0s; border: 0px; max-width: none; max-height: none; min-width: 0px; min-height: 0px; vertical-align: 0px; line-height: normal; text-decoration: none; white-space: nowrap !important;">2bar"將導致"foobar"被添加到字符串緩沖區(qū)螟凭。可能將美元符號(</nobr><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>2</mn><mi>b</mi><mi>a</mi><mi>r</mi><mo>"</mo><mrow class="MJX-TeXAtom-ORD"><mo>將</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>導</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>致</mo></mrow><mo>"</mo><mi>f</mi><mi>o</mi><mi>o</mi><mi>b</mi><mi>a</mi><mi>r</mi><mo>"</mo><mrow class="MJX-TeXAtom-ORD"><mo>被</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>添</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>加</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>到</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>字</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>符</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>串</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>緩</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>沖</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>區(qū)</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>它呀。</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>可</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>能</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>將</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>美</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>元</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>符</mo></mrow><mrow class="MJX-TeXAtom-ORD"><mo>號</mo></mrow><mo stretchy="false">(</mo></math>) 作為替換字符串中的字面值(通過前面使用一個反斜線 ($))包括進來螺男。

注意,在替換字符串中使用反斜線 () 和美元符號 ($) 可能導致與作為字面值替換字符串時所產生的結果不同纵穿。美元符號可視為到如上所述已捕獲子序列的引用下隧,反斜線可用于轉義替換字符串中的字面值字符。

此方法設計用于循環(huán)以及 appendTail 和 find 方法中谓媒。例如淆院,以下代碼將 one dog two dogs in the yard 寫入標準輸出流中:

 Pattern p = Pattern.compile("cat");
 Matcher m = p.matcher("one cat two cats in the yard");
 StringBuffer sb = new StringBuffer();
 while (m.find()) {
     m.appendReplacement(sb, "dog");
 }
 m.appendTail(sb);
 System.out.println(sb.toString());

輸出結果:


image

appendTail

StringBuffer appendTail(StringBuffer sb)
此方法從添加位置開始從輸入序列讀取字符,并將其添加到給定字符串緩沖區(qū)句惯⊥帘纾可以在一次或多次調用 appendReplacement 方法后調用它來復制剩余的輸入序列。

以上例來說抢野,當匹配到第二個cat時拷淘,while語句塊中的代碼就失效了,此時后面的字符串s in the yard就需要使用appendTail方法來補齊指孤,否則輸出結果就是:

image

顯然有所缺失启涯。

group

String group()
返回由以前匹配操作所匹配的輸入子序列。
對于具有輸入序列 s 的匹配器 m恃轩,表達式 m.group() 和 s.substring(m.start(), m.end()) 是等效的结洼。
注意歇万,某些模式(例如琳省,a*)匹配空字符串试躏。當模式成功匹配輸入中的空字符串時尝盼,此方法將返回空字符串峰锁。

group(int group)

String group(int group)
返回在以前匹配操作期間由給定組捕獲的輸入子序列郭厌。
對于匹配器 m卸耘、輸入序列 s 和組索引 g祠饺,表達式 m.group(g) 和 s.substring(m.start(g), m.end(g)) 是等效的敞掘。

捕獲組是從 1 開始從左到右的索引叽掘。組零表示整個模式,因此表達式 m.group(0) 等效于 m.group()玖雁。

如果該匹配成功了更扁,但指定組未能匹配輸入序列的任何部分,則返回 null。注意浓镜,某些組(例如溃列,(a*))匹配空字符串。當這些的組成功匹配輸入中的空字符串時膛薛,此方法將返回空字符串听隐。

        Pattern p = Pattern.compile("\\b\\w+(o\\w+)\\b");
        Matcher m = p.matcher("i love you");
        while (m.find()) {
            System.out.println("整個匹配結果=>"+m.group());
            System.out.println("一組匹配結果=>"+m.group(1));
        }

輸出結果:

image

其他

其他方法要么可以融會貫通,比如start(int)哄啄,要么就是不常用雅任,比如hasAnchoringBounds(),因此在需要的時候可以查看中文文檔咨跌。
奉上連接:Matcher

常用正則

校驗數字的表達式

數字:^[0-9]*$
n位的數字:^\d{n}$
至少n位的數字:^\d{n,}$
m-n位的數字:^\d{m,n}$
零和非零開頭的數字:^(0|[1-9][0-9]*)$
非零開頭的最多帶兩位小數的數字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
帶1-2位小數的正數或負數:^(\-)?\d+(\.\d{1,2})?$
正數沪么、負數、和小數:^(\-|\+)?\d+(\.\d+)?$
有兩位小數的正實數:^[0-9]+(.[0-9]{2})?$
有1~3位小數的正實數:^[0-9]+(.[0-9]{1,3})?$
非零的正整數:^[1-9]\d*$^([1-9][0-9]*){1,3}$^\+?[1-9][0-9]*$
非零的負整數:^\-[1-9][]0-9″*$^-[1-9]\d*$
非負整數:^\d+$^[1-9]\d*|0$
非正整數:^-[1-9]\d*|0$^((-\d+)|(0+))$
非負浮點數:^\d+(\.\d+)?$^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮點數:^((-\d+(\.\d+)?)|(0+(\.0+)?))$^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮點數:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
負浮點數:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮點數:^(-?\d+)(\.\d+)?$^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

校驗字符的表達式

漢字:^[\u4e00-\u9fa5]{0,}$
英文和數字:^[A-Za-z0-9]+$^[A-Za-z0-9]{4,40}$
長度為3-20的所有字符:^.{3,20}$
由26個英文字母組成的字符串:^[A-Za-z]+$
由26個大寫英文字母組成的字符串:^[A-Z]+$
由26個小寫英文字母組成的字符串:^[a-z]+$
由數字和26個英文字母組成的字符串:^[A-Za-z0-9]+$
由數字锌半、26個英文字母或者下劃線組成的字符串:^\w+$^\w{3,20}$
中文禽车、英文、數字包括下劃線:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文拳喻、英文哭当、數字但不包括下劃線等符號:^[\u4E00-\u9FA5A-Za-z0-9]+$^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以輸入含有^%&',;=?$\”等字符:[^%&',;=?$\x22]+
禁止輸入含有~的字符:[^~\x22]+

特殊需求表達式

Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL:[a-zA-z]+://[^\s]*^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手機號碼:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
電話號碼(“XXX-XXXXXXX”、”XXXX-XXXXXXXX”冗澈、”XXX-XXXXXXX”钦勘、”XXX-XXXXXXXX”、”XXXXXXX”和”XXXXXXXX):^($$\d{3,4}-)|\d{3.4}-)?\d{7,8}$
國內電話號碼(0511-4405222亚亲、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
身份證號(15位彻采、18位數字):^\d{15}|\d{18}$
短身份證號碼(數字、字母x結尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帳號是否合法(字母開頭捌归,允許5-16字節(jié)肛响,允許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密碼(以字母開頭,長度在6~18之間惜索,只能包含字母特笋、數字和下劃線):^[a-zA-Z]\w{5,17}$
強密碼(必須包含大小寫字母和數字的組合,不能使用特殊字符巾兆,長度在8-10之間):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12個月(01~09和1~12):^(0?[1-9]|1[0-2])$
一個月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$

xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正則表達式:[\u4e00-\u9fa5]
雙字節(jié)字符:[^\x00-\xff] (包括漢字在內猎物,可以用來計算字符串的長度(一個雙字節(jié)字符長度計2,ASCII字符計1))
空白行的正則表達式:\n\s*\r (可以用來刪除空白行)
HTML標記的正則表達式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (網上流傳的版本太糟糕角塑,上面這個也僅僅能部分蔫磨,對于復雜的嵌套標記依舊無能為力)
首尾空白字符的正則表達式:^\s*|\s*$(^\s*)|(\s*$) (可以用來刪除行首行尾的空白字符(包括空格、制表符圃伶、換頁符等等)堤如,非常有用的表達式)
騰訊QQ號:[1-9][0-9]{4,} (騰訊QQ號從10000開始)
中國郵政編碼:[1-9]\d{5}(?!\d) (中國郵政編碼為6位數字)
IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址時有用)
IP地址:((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}\2

錢的輸入格式

有四種錢的表示形式我們可以接受:”10000.00″ 和 “10,000.00″, 和沒有 “分” 的 “10000″ 和 “10,000″:^[1-9][0-9]*$
這表示任意一個不以0開頭的數字蒲列,但是,這也意味著一個字符”0″不通過搀罢,所以我們采用下面的形式:^(0|[1-9][0-9]*)$
一個0或者一個不以0開頭的數字.我們還可以允許開頭有一個負號:^(0|-?[1-9][0-9]*)$
這表示一個0或者一個可能為負的開頭不為0的數字.讓用戶以0開頭好了.把負號的也去掉蝗岖,因為錢總不能是負的吧.下面我們要加的是說明可能的小數部分:^[0-9]+(.[0-9]+)?$
必須說明的是,小數點后面至少應該有1位數榔至,所以”10.”是不通過的剪侮,但是 “10″ 和 “10.2″ 是通過的:^[0-9]+(.[0-9]{2})?$
這樣我們規(guī)定小數點后面必須有兩位,如果你認為太苛刻了洛退,可以這樣:^[0-9]+(.[0-9]{1,2})?$
這樣就允許用戶只寫一位小數。下面我們該考慮數字中的逗號了杰标,我們可以這樣:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
1到3個數字兵怯,后面跟著任意個 逗號+3個數字,逗號成為可選腔剂,而不是必須:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
備注:這就是最終結果了媒区,別忘了”+”可以用”*”替代。如果你覺得空字符串也可以接受的話(奇怪掸犬,為什么?)最后袜漩,別忘了在用函數時去掉去掉那個反斜杠,一般的錯誤都在這里

(1)過濾出字母的正則表達式

  [^(A-Za-z)]

(2) 過濾出 數字 的正則表達式

[^(0-9)]

(3) 過濾出 中文 的正則表達式

   [^([\\u4e00-\\u9fa5](file://u4e00-//u9fa5))]

(4) 過濾出字母湾碎、數字和中文的正則表達式

   [^(a-zA-Z0-9\\u4e00-\\u9fa5)]
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末宙攻,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子介褥,更是在濱河造成了極大的恐慌座掘,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柔滔,死亡現場離奇詭異溢陪,居然都是意外死亡,警方通過查閱死者的電腦和手機睛廊,發(fā)現死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門形真,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人超全,你說我怎么就攤上這事咆霜。” “怎么了卵迂?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵裕便,是天一觀的道長。 經常有香客問我见咒,道長偿衰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮下翎,結果婚禮上缤言,老公的妹妹穿的比我還像新娘。我一直安慰自己视事,他們只是感情好胆萧,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俐东,像睡著了一般跌穗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虏辫,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天蚌吸,我揣著相機與錄音,去河邊找鬼砌庄。 笑死羹唠,一個胖子當著我的面吹牛,可吹牛的內容都是我干的娄昆。 我是一名探鬼主播佩微,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萌焰!你這毒婦竟也來了哺眯?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤杆怕,失蹤者是張志新(化名)和其女友劉穎族购,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體陵珍,經...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡寝杖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了互纯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瑟幕。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖留潦,靈堂內的尸體忽然破棺而出只盹,到底是詐尸還是另有隱情,我是刑警寧澤兔院,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布殖卑,位于F島的核電站,受9級特大地震影響坊萝,放射性物質發(fā)生泄漏孵稽。R本人自食惡果不足惜许起,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菩鲜。 院中可真熱鬧园细,春花似錦、人聲如沸接校。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛛勉。三九已至鹿寻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诽凌,已是汗流浹背烈和。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留皿淋,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓恬试,卻偏偏與公主長得像窝趣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子训柴,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349