簡體   English   中英

Java正則表達式邊界匹配?

[英]Java regular expression boundary match?

我在一個Java測試套件中發現了以下問題

    Pattern p = Pattern.compile("[wow]*");
    Matcher m = p.matcher("wow its cool");
    boolean b = false;
    while (b = m.find()) {
        System.out.print(m.start() + " \"" + m.group() + "\" ");
    }

輸出似乎如下

0 "wow" 3 "" 4 "" 5 "" 6 "" 7 "" 8 "" 9 "oo" 11 "" 12 ""

直到最后一場比賽很明顯,模式[哇] *貪婪地匹配0或更多'w'和'o'字符,而對於不匹配的字符,包括空格,它會產生空字符串。 然而,在將最后一個'l'與11“”匹配后,以下12“”似乎不清楚。 在測試解決方案中沒有詳細說明,我也無法從javadoc中明確地解決這個問題。 我最好的猜測是邊界特征,但如果有人能提供解釋,我將不勝感激

您看到此行為的原因是您的模式允許空匹配。 換句話說,如果你傳遞一個空字符串,你會在零位置看到一個匹配:

Pattern p = Pattern.compile("[wow]*"); // One of the two 'w's is redundant, but the engine is OK with it
Matcher m = p.matcher("");             // Passing an empty string results in a valid match that is empty
boolean b = false;
while (b = m.find()) {
    System.out.print(m.start() + " \"" + m.group() + "\" ");
}

這將打印0 ""因為空字符串與表達式的任何其他匹配一樣好。

再回到你的例子,每當引擎發現一個匹配項(包括一個空的匹配項)時,它會通過一個字符前進。 “前進一個”意味着引擎在下一個位置考慮弦的“尾部”。 這包括正則表達式引擎處於位置11的時間,即最后一個字符的時間:這里,“尾部”由空字符串組成。 這類似於調用"wow its cool".substring(12) :在這種情況下你也會得到一個空字符串。

引擎將空字符串視為有效輸入,並嘗試將其與表達式匹配,如上例所示。 這會產生匹配,您的程序會正確報告。

  • [wow]*匹配第一個wow弦。 count = 1

  • 由於字符類旁邊的*零或更多 ), [wow]*這個正則表達式將匹配一個空字符串,該字符串存在於與上述模式不匹配的字符之前。 因此它匹配前面存在於第一個空間的邊界或空白空間。 數= 2。

  • its與上述正則表達式不匹配。 所以它匹配每個字符之前存在的空字符串。 因此計數是2+3=5

  • 並且第二個空間與上述正則表達式不匹配。 所以我們得到一個空字符串作為匹配。 5+1=6

  • c與上述正則表達式不匹配。 所以它匹配之前存在的空白空間到c 6+1=7

  • oo與上述正則表達式匹配。 [wow]* 所以它匹配oo ,這被認為是1匹配。 所以我們得到7+1=8作為計數。

  • l不匹配。 數= 9

  • 最后它匹配最后一個字符旁邊的空字符串。 所以現在計數是9+1=10

  • 最后我們都知道m.start()打印相應匹配的起始索引。

DEMO

正則表達式簡單地將模式與輸入匹配,從給定的偏移量開始。 對於最后一場比賽,12的偏移量是在'酷'的最后一個字符之后的位置 - 你可能認為這是字符串的結尾,因此不能用於匹配目的 - 但你錯了。 對於模式匹配,這是一個非常有效的起點。

正如您所述,您的正則表達式包含零字符的可能性,實際上,這是在最后一個字符結束之后但在字符串結束標記之前發生的事情(通常在正則表達式中由$表示)。

換句話說,沒有測試超過最后一個字符的結尾,這意味着不會發生與字符串結尾相關的匹配 - 但是有許多正則表達式構造匹配字符串的結尾(並且你已經在這里顯示其中一個)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM