首頁 > 軟體

Java正規表示式API字元類

2022-06-09 22:01:47

一、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正規表示式 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com