正則表達式中的“量詞”入門介紹

正則表達式中的量詞可以用來指明某個字符串匹配的次數。將在以下描述“貪心量詞”(Greedy)、“厭惡量詞”(reluctant)、“占有量詞”(possessive)這三種量詞。(真的不知道怎么翻譯)。乍一看量詞X?(貪心量詞)、X??(厭惡量詞) 和X?+(占有量詞)好像作用也差不多,因為它們的匹配規則都是匹配“X” 一次或者零次,即X出現一次或者一次都不出現。其實它們有著細微的差別,在本文中最后一部分會說明。

1.png

讓我們用貪心量詞來創建三種不同的正則表達式:a?、a*、a+、。看看如果用空字符串來測匹配會得到什么結果。

先給出以下測試代碼(直接使用終端編譯運行即可):

public class RegexTestHarness {
    public static void main(String[] args){
        Console console = System.console();
        if (console == null) {
            System.err.println("No console.");
            System.exit(1);
        }
        while (true) {

            Pattern pattern =
                    Pattern.compile(console.readLine("%nEnter your regex: "));

            Matcher matcher =
                    pattern.matcher(console.readLine("Enter input string to search: "));

            boolean found = false;
            while (matcher.find()) {
                console.format("I found the text" +
                                " \"%s\" starting at " +
                                "index %d and ending at index %d.%n",
                        matcher.group(),
                        matcher.start(),
                        matcher.end());
                found = true;
            }
            if(!found){
                console.format("No match found.%n");
            }
        }
    }
}

Enter your regex: a?
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.

Enter your regex: a*
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.

Enter your regex: a+
Enter input string to search:
No match found.

零長度匹配

在上面的例子中,前兩個例子可以匹配成功是因為表達式a?和a*允許字符串中不出現‘a’字符。你會看到開始和結束的下標都是0。空字符串""沒有長度,因此這個正則在開始位置(即下標為0)即匹配成功。像這一類的匹配稱之為“零長度匹配”。零長度匹配會在以下三種情況出現:
1.一個空字符串匹配。
2.和字符串的開端匹配,即下標為0的地方匹配。(開端即是空字符串)
3.和字符串結束的位置匹配。(結束即是空字符串)
4.任意兩個字符之間,如"bc",b和c之間即存在一個空字符串""。

用“foo”這個字符串作為例子,下標的位置對應關系為

Paste_Image.png

即index=0和index=3的地方會匹配。

零長度匹配是非常容易辨別出來,因為他們開始的位置和結束的位置是同一下標。

然我們再看幾個列子,輸入一個“a”字符。
Enter your regex: a?
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.

Enter your regex: a*
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.

Enter your regex: a+
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.

以上三個量詞都能找到字符“a”,但是前兩個例子在下標為1處匹配,也就是字符的結尾處。記住,匹配器查找到下標0和1之間的“a”,該程序會一直匹配到沒有匹配為止。

接下來輸入"ababaaaab",看下會得到什么輸出。輸出如下:
Enter your regex: a?
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "a" starting at index 4 and ending at index 5.
I found the text "a" starting at index 5 and ending at index 6.
I found the text "a" starting at index 6 and ending at index 7.
I found the text "a" starting at index 7 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.

Enter your regex: a*
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.

Enter your regex: a+
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.

讀者可以自己推敲為什么會得出以上結果。

如果要限制某個字符出現的次數,可以使用大括號"{}"。如:
匹配“aaa”
Enter your regex: a{3}
Enter input string to search: aa
No match found.

Enter your regex: a{3}
Enter input string to search: aaa
I found the text "aaa" starting at index 0 and ending at index 3.

Enter your regex: a{3}
Enter input string to search: aaaa
I found the text "aaa" starting at index 0 and ending at index 3.

對于第三個實例,要注意的是,當匹配了前三個a,后面的匹配和前面3個a沒有任何關系,正則會繼續和“aaa”后面的內容繼續嘗試匹配。

被量詞修飾的子表達式 如:
Enter your regex: (dog){3}
Enter input string to search: dogdogdogdogdogdog
I found the text "dogdogdog" starting at index 0 and ending at index 9.
I found the text "dogdogdog" starting at index 9 and ending at index 18.

Enter your regex: dog{3}
Enter input string to search: dogdogdogdogdogdog
No match found.

對于第二個例子,正則表達式匹配的內容應該是"do",后面緊跟3個"g",因此第二個例子無法匹配。

再看多一個例子:
Enter your regex: [abc]{3}
Enter input string to search: abccabaaaccbbbc
I found the text "abc" starting at index 0 and ending at index 3.
I found the text "cab" starting at index 3 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.
I found the text "ccb" starting at index 9 and ending at index 12.
I found the text "bbc" starting at index 12 and ending at index 15.

Enter your regex: abc{3}
Enter input string to search: abccabaaaccbbbc
No match found.

貪婪模式和厭惡模式和占有模式的區別
貪婪模式之所以被稱為貪婪模式,是因為貪婪模式會盡可能的去匹配更多的內容,如果匹配不成功,將會進行回溯,直至匹配成功或者不成功。
看看下面例子:
Enter your regex: .*foo // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.
第一個例子采用貪婪模式,.
部分和整個字符串"xfooxxxxxxfoo"匹配,接著正則中foo部分和字符串"xfooxxxxxxfoo"的剩余部分匹配,即空字串"",發現匹配不成功。開始回溯, .*與"xfooxxxxxxfo"匹配,正則中的foo部分和"xfooxxxxxxfo"剩余部分進行匹配,即"o",發現不匹配,繼續回溯。重復上訴過程,直到匹配成功。由于是貪婪模式,一旦成功,將不會繼續匹配,匹配終止。

第二個例子采用的是厭惡模式(非貪婪模式),剛好和貪婪模式相反,一開始只會和字符串開始位置進行匹配,此例中,即和空字符串""匹配,匹配成功后,正則中的foo部分和字符串中的開頭三個字符"xfo"匹配,發現匹配不成功。.*?開始和第一個字符匹配,即"x",匹配成功,接著正則中的foo和字符串中的"foo"匹配。至此整個正則第一次匹配成功。接著繼續匹配,接下來的匹配內容為"xxxxxxfoo",采用相同的規則繼續匹配,第二次匹配成功的字符串為"xxxxxxfoo"。直至整個字符串被消耗完畢才終止匹配。

第三個例子是占有模式。該模式只進行一次匹配。不進行回溯嘗試,在次例中,.*+與"xfooxxxxxxfoo"匹配,正則中的foo和空字符串""匹配,匹配失敗。將不進行回溯嘗試。匹配結束。

以上內容大部分是翻譯The Java? Tutorials中關于正則的教程

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內容

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,734評論 0 23
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,809評論 18 139
  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的閱讀 13,512評論 5 6
  • 第八章 肖宇最愛吃的烤地瓜 放學回家的時候,我就聞到一個特別熟悉的味道,我四處張望,果真在街角對面看到一個大爺在賣...
    季霏閱讀 367評論 0 0
  • 六月的雪, 離鄉的愁, 那一壇梨花釀, 曾裹挾了誰, 才逃了心, 又縈懷滿傷。 塵世的憂, 空濛的香, 那一口梨花...
    鈐花客閱讀 497評論 0 1