Java正則表達(dá)式之API

Predefined字符類(lèi)
Java正則表達(dá)式API也接受預(yù)定義的字符類(lèi)澡腾。上面的一些字符類(lèi)可以用更短的形式表示,盡管這會(huì)降低代碼的直觀性疙挺。這個(gè)正則表達(dá)式的Java版本的一個(gè)特殊方面是轉(zhuǎn)義字符。

正如我們將看到的,大多數(shù)字符都以反斜杠開(kāi)頭患膛,這在Java中有特殊的意義。對(duì)于要由模式類(lèi)編譯的這些耻蛇,必須轉(zhuǎn)義前導(dǎo)反斜杠踪蹬,即 .\d 變?yōu)?\d 。

匹配的數(shù)字臣咖,相當(dāng)于 [0-9] :

@Test
public void givenDigits_whenMatches_thenCorrect() {
int matches = runTest("\d", "123");

assertEquals(matches, 3);

}
匹配非數(shù)字延曙,相當(dāng)于 [^0-9] :

@Test
public void givenNonDigits_whenMatches_thenCorrect() {
int mathces = runTest("\D", "a6c");

assertEquals(matches, 2);

}
匹配空白:

@Test
public void givenWhiteSpace_whenMatches_thenCorrect() {
int matches = runTest("\s", "a c");

assertEquals(matches, 1);

}
匹配非空白:

@Test
public void givenNonWhiteSpace_whenMatches_thenCorrect() {
int matches = runTest("\S", "a c");

assertEquals(matches, 2);

}
匹配一個(gè)單詞字符,相當(dāng)于 [a-zA-Z_0-9] :

@Test
public void givenWordCharacter_whenMatches_thenCorrect() {
int matches = runTest("\w", "hi!");

assertEquals(matches, 2);

}
匹配非單詞字符:

@Test
public void givenNonWordCharacter_whenMatches_thenCorrect() {
int matches = runTest("\W", "hi!");

assertEquals(matches, 1);

}
Quantifiers
Java正則表達(dá)式API還允許我們使用Quantifiers亡哄。通過(guò)指定匹配的出現(xiàn)次數(shù)枝缔,我們可以進(jìn)一步調(diào)整匹配的行為。

要匹配零次或一次文本蚊惯,我們使用 愿卸? 量詞:

@Test
public void givenZeroOrOneQuantifier_whenMatches_thenCorrect() {
int matches = runTest("\a?", "hi");

assertEquals(matches, 3);

}
或者,我們可以使用大括號(hào)語(yǔ)法截型,Java regex API也支持這種語(yǔ)法:

@Test
public void givenZeroOrOneQuantifier_whenMatches_thenCorrect2() {
int matches = runTest("\a{0,1}", "hi");

assertEquals(matches, 3);

}
本例介紹了零長(zhǎng)度匹配的概念趴荸。碰巧的是,如果一個(gè)量詞的匹配閾值為零宦焦,它總是匹配文本中的所有內(nèi)容发钝,包括每個(gè)輸入末尾的一個(gè)空字符串。這意味著即使輸入為空波闹,它也將返回一個(gè)零長(zhǎng)度匹配酝豪。

這就解釋了為什么在上面的示例中,盡管字符串長(zhǎng)度為2精堕,但我們?nèi)缘玫?個(gè)匹配項(xiàng)孵淘。第三個(gè)匹配項(xiàng)是長(zhǎng)度為零的空字符串。

為了匹配零次或無(wú)限次的文本歹篓,我們使用 * 量詞瘫证,它與揉阎?:

@Test
public void givenZeroOrManyQuantifier_whenMatches_thenCorrect() {
int matches = runTest("\a*", "hi");

 assertEquals(matches, 3);

}
支持的替代方案:

@Test
public void givenZeroOrManyQuantifier_whenMatches_thenCorrect2() {
int matches = runTest("\a{0,}", "hi");

assertEquals(matches, 3);

}
差異量詞為+,匹配閾值為1背捌。如果所需的字符串根本不出現(xiàn)毙籽,則將不存在匹配項(xiàng),甚至不存在長(zhǎng)度為零的字符串:

@Test
public void givenOneOrManyQuantifier_whenMatches_thenCorrect() {
int matches = runTest("\a+", "hi");

assertFalse(matches);

}
支持的替代方案:

@Test
public void givenOneOrManyQuantifier_whenMatches_thenCorrect2() {
int matches = runTest("\a{1,}", "hi");

assertFalse(matches);

}
正如在Perl和其他語(yǔ)言中一樣毡庆,大括號(hào)語(yǔ)法可用于多次匹配給定文本:

@Test
public void givenBraceQuantifier_whenMatches_thenCorrect() {
int matches = runTest("a{3}", "aaaaaa");

assertEquals(matches, 2);

}
在上面的例子中坑赡,我們得到了兩個(gè)匹配項(xiàng),因?yàn)橹挥挟?dāng)a在一行中出現(xiàn)三次時(shí)扭仁,才會(huì)出現(xiàn)匹配項(xiàng)垮衷。但是,在下一次測(cè)試中乖坠,我們不會(huì)得到匹配搀突,因?yàn)槲谋驹谝恍兄兄怀霈F(xiàn)兩次:

@Test
public void givenBraceQuantifier_whenFailsToMatch_thenCorrect() {
int matches = runTest("a{3}", "aa");

assertFalse(matches > 0);

}
當(dāng)我們?cè)诖罄ㄌ?hào)中使用范圍時(shí),匹配將是貪婪的熊泵,從范圍的高端匹配:

@Test
public void givenBraceQuantifierWithRange_whenMatches_thenCorrect() {
int matches = runTest("a{2,3}", "aaaa");

assertEquals(matches, 1);

}
我們已經(jīng)指定了至少兩次但不超過(guò)三次仰迁,所以我們得到一個(gè)匹配,匹配者看到一個(gè) aaa 和一個(gè)無(wú)法匹配的 a 顽分。

然而徐许,API允許我們指定一種懶惰或不情愿的方法,以便匹配器可以從范圍的低端開(kāi)始卒蘸,在這種情況下雌隅,匹配兩個(gè)匹配項(xiàng)aa和aa:

@Test
public void givenBraceQuantifierWithRange_whenMatchesLazily_thenCorrect() {
int matches = runTest("a{2,3}?", "aaaa");

assertEquals(matches, 2);

}
Capturing Groups
API還允許我們通過(guò)Capturing Groups將多個(gè)角色視為一個(gè)單元。

它會(huì)將數(shù)字附加到Capturing Groups缸沃,并允許使用這些數(shù)字進(jìn)行反向引用恰起。

在本節(jié)中,我們將看到一些關(guān)于如何在Java正則表達(dá)式API中使用Capturing Groups的示例趾牧。

讓我們使用一個(gè)僅當(dāng)輸入文本包含兩個(gè)相鄰數(shù)字時(shí)才匹配的Capturing Groups:

@Test
public void givenCapturingGroup_whenMatches_thenCorrect() {
int maches = runTest("(\d\d)", "12");

assertEquals(matches, 1);

}
上面匹配的數(shù)字是1检盼,使用 back 引用告訴匹配者我們想要匹配文本匹配部分的另一個(gè)匹配項(xiàng)。這樣做翘单,而不是:

@Test
public void givenCapturingGroup_whenMatches_thenCorrect2() {
int matches = runTest("(\d\d)", "1212");

assertEquals(matches, 2);

}
如果輸入有兩個(gè)單獨(dú)的匹配項(xiàng)吨枉,我們可以有一個(gè)匹配項(xiàng),但使用反向引用傳播相同的正則表達(dá)式匹配項(xiàng)以跨越輸入的整個(gè)長(zhǎng)度:

@Test
public void givenCapturingGroup_whenMatchesWithBackReference_
thenCorrect() {
int matches = runTest("(\d\d)\1", "1212");

assertEquals(matches, 1);

}
我們必須重復(fù)正則表達(dá)式哄芜,而無(wú)需反向引用貌亭,才能獲得相同的結(jié)果:

@Test
public void givenCapturingGroup_whenMatches_thenCorrect3() {
int matches = runTest("(\d\d)(\d\d)", "1212");

assertEquals(matches, 1);

}
類(lèi)似地,對(duì)于任何其他重復(fù)次數(shù)忠烛,反向引用可以使匹配者將輸入視為單個(gè)匹配:

@Test
public void givenCapturingGroup_whenMatchesWithBackReference_
thenCorrect2() {
int matches = runTest("(\d\d)\1\1\1", "12121212");

assertEquals(matches, 1);

}
但如果你甚至改變了最后一個(gè)數(shù)字属提,匹配就會(huì)失敗:

@Test
public void givenCapturingGroupAndWrongInput_
whenMatchFailsWithBackReference_thenCorrect() {
int matches = runTest("(\d\d)\1", "1213");

assertFalse(matches > 0);

}
重要的是不要忘記轉(zhuǎn)義反斜杠美尸,這在Java語(yǔ)法中至關(guān)重要冤议。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市师坎,隨后出現(xiàn)的幾起案子恕酸,更是在濱河造成了極大的恐慌,老刑警劉巖胯陋,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蕊温,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡遏乔,警方通過(guò)查閱死者的電腦和手機(jī)义矛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)盟萨,“玉大人凉翻,你說(shuō)我怎么就攤上這事∧砑ぃ” “怎么了制轰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)胞谭。 經(jīng)常有香客問(wèn)我垃杖,道長(zhǎng),這世上最難降的妖魔是什么丈屹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任调俘,我火速辦了婚禮,結(jié)果婚禮上旺垒,老公的妹妹穿的比我還像新娘彩库。我一直安慰自己,他們只是感情好袖牙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布侧巨。 她就那樣靜靜地躺著,像睡著了一般鞭达。 火紅的嫁衣襯著肌膚如雪司忱。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天畴蹭,我揣著相機(jī)與錄音坦仍,去河邊找鬼。 笑死叨襟,一個(gè)胖子當(dāng)著我的面吹牛繁扎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼梳玫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼爹梁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起提澎,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤姚垃,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后盼忌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體积糯,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年谦纱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了看成。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡跨嘉,死狀恐怖川慌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情偿荷,我是刑警寧澤窘游,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站跳纳,受9級(jí)特大地震影響忍饰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寺庄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一艾蓝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧斗塘,春花似錦赢织、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至贞岭,卻和暖如春八毯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞄桨。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工话速, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芯侥。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓泊交,卻偏偏與公主長(zhǎng)得像乳讥,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子廓俭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355