有時,咱們想用正則匹配以某個子串開頭,且以某個子串或字符結尾的子字符串,可是結尾的字串或字符在原字符串中出現了屢次,但咱們只想匹配從開始處到第一次出現的地方,換句話說,想獲得開始和結尾之間內容最少的匹配。html
一般使用以下字符類描述前導字符的重複特徵:
1. ?: 告訴引擎匹配前導字符0次或一次。事實上是表示前導字符是可選的。
2. +: 告訴引擎匹配前導字符1次或屢次。
3. *: 告訴引擎匹配前導字符0次或屢次。
4. {min, max}: 告訴引擎匹配前導字符min次到max次。min和max都是非負整數。若是有逗號而max被省略了,則表示max沒有限制;若是逗號和max都被省略了,則表示重複min次。
所以 {0,} 和 * 同樣,{1,} 和 + 的做用同樣。正則表達式
默認狀況下,? + * {min, max}都是貪婪的,也就是說,它會根據前導字符去匹配儘量多的內容。學習
非貪婪就是匹配儘量少的內容。測試
結合實例來分析哈基於正則的引擎對文本的匹配過程。原始字符串:This is a <EM>first</EM> test
,使用正則<.+>來匹配HTML標籤,指望第一次匹配獲得<EM>
,第二次匹配獲得</EM>
,實際倒是第一次匹配就獲得了<EM>first</EM>
。.net
來看看匹配過程,第一個記號是<
,這是一個文本字符,匹配其自身。第二個符號是.
,匹配了字符E
,而後+
一直能夠匹配其他的字符,直到一行的結束。而後到了換行符,匹配失敗(.
不匹配換行符)。因而引擎開始對下一個正則表達式符號進行匹配,即試圖匹配>
。到目前爲止,<.+
已經匹配了<EM>first</EM> test
。引擎會試圖將>
與換行符進行匹配,結果失敗了。因而引擎進行回溯。回溯後的匹配情況是 <.+
匹配 <EM>first</EM> tes
。因而引擎將>
與t
進行匹配。顯然仍是會失敗。這個過程繼續,直到 <.+
匹配 <EM>first</EM
,>
與>
匹配。因而引擎找到了一個匹配<EM>first</EM>
。記住,正則導向的引擎是急切的,因此它會急着報告它找到的第一個匹配。而不是繼續回溯,即便可能會有更好的匹配,例如<EM>
。因此咱們能夠看到,因爲+
的貪婪性,使得正則表達式引擎返回了一個最左邊的最長的匹配。code
若是想獲得指望的結果,就須要啓用非貪婪模式:<.+?>
htm
總結:若是是貪婪匹配模式,正則引擎會一直匹配到字符串最後;當匹配爲false時,就回溯以找到倒數第一個匹配位置,返回匹配結果。 若是是非貪婪匹配模式,正則引擎會匹配到符合pattern的末尾位置那個字符,而後再日後走一步,發現匹配爲false時,就回溯以找到最近一個匹配爲true的位置,返回匹配結果。blog
例如,原始字符串:資源
{"accesskey":{"acccessKeyId":"XhUURxsMlJE6EiXf","accessKeySecret":"Q9fMpgBgRnKycMRD28MMkkFMbiNkbY"},"dbGrant":{"0000031736":"READWRITE"},"dbSchemaId":"0000031737"}
如今想把這部分敏感信息替換爲空字符串:字符串
"accesskey":{"acccessKeyId":"XhUURxsMlJE6EiXf","accessKeySecret":"Q9fMpgBgRnKycMRD28MMkkFMbiNkbY"},
先不考慮結尾的逗號,嘗試正則:"accesskey":\{.+\},直接匹配至原始字符串結尾的}字符,由於引擎默認會匹配儘量多的內容。
考慮到貪婪性,將正則修改成:"accesskey":\{.+\}+?,匹配結果同樣。納尼?難道我對貪婪性的理解有問題。梳理哈使用姿式,我指望它匹配到開始位置以後出現的第一個}字符,對應的表達式部分爲\}+?。套用非貪婪模式分析問題,指望對一個或多個}字符進行匹配,且匹配儘量少的內容,但在原始串中,}字符都是分開的,沒有連續,不管如何只能匹配一個單獨的}字符。可見對}字符開啓非貪婪模式匹配行不通。
想要匹配到開始位置以後出現的第一個}字符 也能夠表達爲 開始位置和末尾}字符之間的內容最少,對應正則部分修改成:.+?,完整表達式:"accesskey":\{.+?\},測試匹配結果,妥妥的。
正確理解正則回溯
深刻淺出之正則(一)
正則進階(二)- 回溯引用、先後查找、嵌入條件
正則學習筆記(6)向前查找和向後查找
正則 - 向前匹配、向後匹配、負向前匹配、負向後匹配