Java正則表達式API字符類

一、Predefined字符類

Java正則表達式API也接受預定義的字符類。上面的一些字符類可以用更短的形式表示,盡管這會降低代碼的直觀性。這個正則表達式的Java版本的一個特殊方面是轉義字符。

正如我們將看到的,大多數字符都以反斜杠開頭,這在Java中有特殊的意義。對於要由模式類編譯的這些,必須轉義前導反斜杠,即.\d變為\\d

匹配的數字,相當於[0-9]

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

匹配非數字,相當於[^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);
}

匹配一個單詞字符,相當於[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正則表達式API還允許我們使用Quantifiers。通過指定匹配的出現次數,我們可以進一步調整匹配的行為。

要匹配零次或一次文本,我們使用量詞:

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

或者,我們可以使用大括號語法,Java regex API也支持這種語法:

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

本例介紹瞭零長度匹配的概念。碰巧的是,如果一個量詞的匹配閾值為零,它總是匹配文本中的所有內容,包括每個輸入末尾的一個空字符串。這意味著即使輸入為空,它也將返回一個零長度匹配。

這就解釋瞭為什麼在上面的示例中,盡管字符串長度為2,但我們仍得到3個匹配項。第三個匹配項是長度為零的空字符串。

為瞭匹配零次或無限次的文本,我們使用*量詞,它與?:

@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。如果所需的字符串根本不出現,則將不存在匹配項,甚至不存在長度為零的字符串:

@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和其他語言中一樣,大括號語法可用於多次匹配給定文本:

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

在上面的例子中,我們得到瞭兩個匹配項,因為隻有當a在一行中出現三次時,才會出現匹配項。但是,在下一次測試中,我們不會得到匹配,因為文本在一行中隻出現兩次:

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

當我們在大括號中使用范圍時,匹配將是貪婪的,從范圍的高端匹配:

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

我們已經指定瞭至少兩次但不超過三次,所以我們得到一個匹配,匹配者看到一個aaa和一個無法匹配的a

然而,API允許我們指定一種懶惰或不情願的方法,以便匹配器可以從范圍的低端開始,在這種情況下,匹配兩個匹配項aa和aa:

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

三、Capturing Groups

API還允許我們通過Capturing Groups將多個角色視為一個單元。它會將數字附加到Capturing Groups,並允許使用這些數字進行反向引用。

在本節中,我們將看到一些關於如何在Java正則表達式API中使用Capturing Groups的示例。

讓我們使用一個僅當輸入文本包含兩個相鄰數字時才匹配的Capturing Groups:

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

上面匹配的數字是1,使用back引用告訴匹配者我們想要匹配文本匹配部分的另一個匹配項。這樣做,而不是:

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

如果輸入有兩個單獨的匹配項,我們可以有一個匹配項,但使用反向引用傳播相同的正則表達式匹配項以跨越輸入的整個長度:

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

我們必須重復正則表達式,而無需反向引用,才能獲得相同的結果:

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

類似地,對於任何其他重復次數,反向引用可以使匹配者將輸入視為單個匹配:

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

但如果你甚至改變瞭最後一個數字,匹配就會失敗:

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

重要的是不要忘記轉義反斜杠,這在Java語法中至關重要。

到此這篇關於Java正則表達式API字符類的文章就介紹到這瞭,更多相關Java正則表達式 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: