正則表示式的非捕獲組
ref:
http://www.cnblogs.com/graphics/archive/2010/06/02/1749707.html
http://www.cnblogs.com/yakun/p/3795589.html
原文符號
因為?在正則表示式中有特殊的含義,所以如果想匹配?本身,則需要轉義,\?
有無量詞
問號可以表示重複前面內容的0次或一次,也就是要麼不出現,要麼出現一次。
非貪婪匹配
貪婪匹配
在滿足匹配時,匹配儘可能長的字串,預設情況下,採用貪婪匹配
string pattern1 = @"a.*c"; // greedy match
Regex regex = new Regex(pattern1);
regex.Match("abcabc"); // return "abcabc"
非貪婪匹配
在滿足匹配時,匹配儘可能短的字串,使用?來表示非貪婪匹配
string pattern1 = @"a.*?c"; // non-greedy match
Regex regex = new Regex(pattern1);
regex.Match("abcabc"); // return "abc"
幾個常用的非貪婪匹配Pattern
- *? 重複任意次,但儘可能少重複
- +? 重複1次或更多次,但儘可能少重複
- ?? 重複0次或1次,但儘可能少重複
- {n,m}? 重複n到m次,但儘可能少重複
- {n,}? 重複n次以上,但儘可能少重複
不捕捉模式
如何關閉圓括號的捕獲能力?而只是用它來做分組,方法是在左括號的後邊加上:?,這裡第一個圓括弧只是用來分組,而不會佔用捕獲變數,所以$1的內容只能是steak或者burger,而永遠不可能是bronto。
while(<>){
if(/(?:bronto)(steak|burger)/){
print "Fred wants a $1\n" ;
}
}
讀jQuery原始碼,其中不可避免的要弄明白正則表示式,在此對非捕獲組(non-capturing)進行了一些梳理。
關於捕獲的一些主要用法
- (?:X)
- (?=X)
- (?<=X)
- (?!X)
- (?<!X)
捕獲
要書明白捕獲,就要先從分組開始。重複單字元我們可以使用限定符,如果重複字串,用什麼呢? 對!用小括號,小括號裡包裹指定字表達式(子串),這就是分組。之後就可以限定這個子表示的重複次數了。
那麼,什麼是捕獲呢?使用小括號指定一個子表示式後,匹配這個子表示式的文字(即匹配的內容)可以在表示式或者其他過程中接著用,怎麼用呢?至少應該有個指標啥的引用它吧? 對!預設情況下,每個分組(小括號)會自動
擁有一個組號,從左到右,以分組的左括號為標誌,第一個出現的分組組號為1,後續遞增。如果出現巢狀,
例如:
“aabcd”
採用正則 (a(b))(c)
match 結果入下:
分組 | 捕獲 |
---|---|
$1(group1) | ab |
$2(group2) | b |
$3(group3) | c |
繼續漲姿勢。
一、(?:)非捕獲組走起。
由下面一個例子引發對非捕獲組的學習。
有兩個金額:6000¥ 和 1000$。
需求是得到金額和貨幣種類。
『廢話少說,多用正則』:
(\d+)+([$¥])
輸出結果為:
OK,滿足了要求。這裡的正則分成了兩個組,一個是(d+),一個是(¥$),前一個組($1)匹配金額,後一個組($2)匹配貨幣種類。
現在,需求變了!! 我需要這個正則同時可以匹配浮點數小數點前面的整數。如10010.86¥,提煉出 10010 和 ¥。
那麼正則如下:
(\d+)(\.?)(\d)([$¥])
這裡用括號分了四組,所以要輸出金額的整數部分和種類,要分別輸了$1,$4了。如果輸出部分和正則是分開的,我希望只修改正則而不去修改輸出部分的程式碼,也就是還是用$1,$2作為輸出。由此可以引出非捕獲組(?:)。
把前面的正則修改為:
(\d+)(?:\.?)(?:\d+)([¥$])$
這樣,還是用$1,$2做為輸出,同樣輸出了 10010 和 ¥
這個正則的中間兩個組用到的就是非捕獲組(?:),它可以理解為只分組而不捕獲。
二、(?=)和(?<=) 前後查詢
有的資料把它們叫做肯定式向前查詢和肯定式向後查詢;
有的資料也叫做肯定順序環視和肯定逆序環視。
1、直接看下面的例子:
[0-9a-z]{2}(?=aa) var str = "12332aa438aaf";
Match List:
1 | 32 |
2 | 38 |
這個正則的意思是:匹配這麼一個字串,它要滿足:是兩位字元(數字,或字母),且後面緊跟著兩個a。
分析一下:
32aa 這個子串滿足這個條件,所以可以匹配到,又因為 (?=) 的部分是不捕獲的,所以輸出的只是 32,不包括aa。同理 38aa 也匹配這個正則,而輸出僅是 38。
再深入看一下:
當str第一次匹配成功輸出 32 後,程式要繼續向後查詢是否還有匹配的其它子串。那麼這時應該從 32aa 的後一位開始向後查詢,還是從 32 的後一位呢?也就是從索引 5 開始還是從 7 開始呢?有人可能想到是從 32aa 的下一位開始往後找,因為 32aa 匹配了正則,所以下一位當然是它的後面也就是從 4 開始。但實際上是從 32 的後一位也就是第一個 a 開始往後找。原因還是 (?=) 是非捕獲的。
查閱API文件是這麼註釋的:
(?=X) X, via zero-width positive lookahead
可見zero-width(零寬度)說的就是這個意思。
現在,把字串寫的更有意思些:str = "aaaaaaaa";
看一下它的輸出: aa aa aa
分析一下:
這個字串一共有8個a。
第一次匹配比較容易找到,那就是前四個:aaaa ,當然第三和第四個 a 是不捕獲的,所以輸出是第一和第二個a;
接著繼續查詢,這時是從第三個a開始,三到六,這4個a區配到了,所以輸出第三和第四個a;
接著繼續查詢,這時是從第五個a開始,五到八,這4個a區配到了,所以輸出第五和第六個a;
接著往後查詢,這時是從第七個a開始,顯然,第七和第八個a,不滿足正則的匹配條件,查詢結束。
我們再延伸一下,剛說的情況的是(?=)放在捕獲的字串後面,它如果放在前面又是什麼結果呢?
例子換成:
(?=hopeful)hope
它的輸出是hope。
正則的意思是:是否能匹配hopeful,如果能,則捕獲hopeful中的hope。當然繼續向後查詢匹配的子串,是從f開始。
比較一下可以看出,(?=hopeful)hope 和 hope(?=ful),兩個正則的效果其實是一樣的。
2、下面說一下 (?<=)
把正則改一下,
(?<=aa)[0-9a-z]{2};
字串還是str = "12332aa438aaf";
它的輸出:43。
這個正則的意思是:匹配這麼一個字串,它要滿足:是兩位字元(數字或字母),且前面緊跟的是兩個字母 a。
同樣,深入一下,把str換成str = "aaaaaaaa";看一下輸出是什麼,同樣也是:aa aa aa
分析一下:
第一次匹配不用說,是前四個a,輸出的是第三和第四個a;
繼續向後查詢,從第五個a開始,程式發現,第五個和第六個a滿足,因為是兩位字元,且滿足前面緊跟著兩個a(第三和第四個a)。所以匹配成功,輸出第五個和第六個a;
繼續向後查詢,從第七個a開始,程式發現,第七個和第八個a滿足,因為是兩位字元,且滿足前面緊跟著兩個a(第五和第六個a)。所以匹配成功,輸出第七和第八個a。查詢結束。
三、(?!)和(?<!) 逆襲!
從外觀上看,和前面一組很相似,區別就是把 ‘=’ 換成了 ‘!’
那麼意義剛好也是相反的。
[0-9a-z]{2}(?!aa)
意思是:匹配兩個字元,且後面緊跟著的不是aa
(?<!aa)[0-9a-z]{2}
意思是:匹配兩個字元,且前面緊跟著的不是aa
用法和前面講的差不多,這裡不再詳述。
相關推薦
java 正則表示式 非捕獲組(特殊構造
在 java api 文件中的正則表示式關於特殊構造(非捕獲組)的說明看不懂。例如:(?:X) X,作為非捕獲組 (?idmsux-idmsux) Nothing,但是將匹配標誌由 on 轉為 off (?idmsux-idmsux:X) X,作為帶有給定標誌 on - off 的非捕獲組 (?=X
java正則表示式 非捕獲組詳解
這幾天看了下正則表示式,對非捕獲組(non-capturing)進行下總結。 主要總結 1個 + 2組 一共5個。 (?:X) (?=X) (?<=X) (?!X) (?<!X) 一、先從(?:)非捕獲組說起。 下面由一個例子引出非捕獲組。 有兩個金額:889
正則表示式——非捕獲分組
目前為止,總共介紹了括號的三種用途: 分組,將相關的語速歸攏到一起,構成單個元素;多選結構,規定可能出現的多個子表達示;引用分組,將子表示式匹配的文字儲存起來,供之後引用。 這三種用途並不是彼此獨立的,而是互相重疊的: 單純的分組可以視為“只包含一個多選分支的多選結構”;整個多選結構也會被視為單個元
關於java正則表示式非捕獲型括號和捕獲型括號的研究
今天在做一個正則表示式的解析時,突然看見一個?:的例子,就看不懂了,然後在網上查了下,竟然是非捕獲型括號,意思就是匹配pattern,但不包含在match的group方法裡面。 (?: pattern)是非捕獲型括號 匹配pattern,
PHP正則中的捕獲組與非捕獲組
今天遇到一個正則匹配的問題,忽然翻到有捕獲組的概念,手冊上也是一略而過,百度時無意翻到C#和Java中有對正則捕獲組的特殊用法,搜尋關鍵詞有PHP時竟然沒有相關內容,自己試了一下,發現在PHP中也是可行的,於是總結一下,分享的同時也希望有大神和細心的學習者找到我理解中出現的問題。 什麼是捕獲組 我
Java正則表達式-捕獲組
mpi matcher java正則 col while 捕獲 result return pat private Set<String> getCodes(String s) { Set<String> resultSet
正則表示式——POSIX字元組
前面介紹了常用的字元組,但是在某些文件中,你可能會發現類似[:digit:]、[:lower:]之類的字元組,看起來不難理解(digit就是"數字",lower就是"小寫"),但又很奇怪,它們就是POSIX字元組(POSIX Character Class)。因為某些語言的文件中出現了這些字元組,為避免困惑,
正則表示式——普通字元組
字元組表示“在同一個位置可能出現的各種字元”, 其寫法是在一對方括號 [ 和 ] 之間列出所有可能出現的字元。 例 1 - 1 判斷數字字元的虛擬碼 charStr == "0" || charStr == "1" ··· || charStr == "9" 這種解法的問題在與太過於煩瑣 例 1 -
正則表示式非貪婪模式的應用
貪婪模式又叫匹配優先模式,在整個表示式匹配成功的前提下,儘可能多的匹配,而非貪婪模式恰恰相反,在整個表示式匹配成功的前提下,儘可能少的匹配,針對的量詞包括: {m, n} {m, } ? * + 從書寫正則表示式的差異來看,它們的唯一區別在於非貪婪模式在
java正則表示式之捕獲分組與Back引用
一.捕獲分組 java正則表示式中以()括起來的內容表示一個分組,像((A)(B(C)))這個表示式中,共存在四個分組: 1.ABC 2.A 3.BC 4.C 很容易發現,分組是按照左邊的括號出現的順序來標號的 這就是捕獲分組 二.Back引用 我們以下面這個正則表示式為例
【JavaScript】正則表示式--非貪婪模式擷取任意字串的筆記
場景要將下面的字串擷取兩個{title:***,url:***}來。12345<script>{title:'RegExp 物件參考手冊',url:'http://sodino.com/regexp.asp'},{title:'w3cSchool script', url:'http://www.
正則表示式的非捕獲組
ref: http://www.cnblogs.com/graphics/archive/2010/06/02/1749707.html http://www.cnblogs.com/yakun/p/3795589.html 原文符號 因為?在正則表示式中有特殊的含
正則表示式----平衡組、捕獲組、非捕獲組
正則表示式----平衡組 請參考http://xuedong.iteye.com/blog/1117195正則表示式----捕獲組 請參考http://blog.csdn.net/lxcnn/article/details/4146148正則表示式----非捕獲組 請參考ht
正則表示式——捕獲組和反向引用
正則表示式的捕獲組和反向引用: 使用小括號指定一個子表示式後,匹配這個子表示式的文字(也就是此分組捕獲的內容)可以在表示式或其他程式中作進一步處理。預設情況下,每個分組會自動擁有一個組號,規則是:從左向右,以分組的左括號為標誌,第一個出現的分組的組號為1,第二
csdn—正則表示式當中的捕獲組
捕獲組 捕獲組是把多個字元當成一個單獨的單元進行處理的方法。 這個方法是通過對括號裡面的字元進行分組來進行建立的。 打個比方來說,正則表示式(dog)建立了單一分組,組裡面是包含了”d”,”o”,”g”這三個東西的。 那麼捕獲組是什麼意思呢,就是通過從左到右計算它的開括號
正則表示式之分組捕獲、條件表示式、平衡組
其實我是想說平衡組,但我並是想寫一篇給零基礎的朋友們閱讀,我希望你是對正則有所瞭解,對平衡組不太瞭解的朋友閱讀。如果已經瞭解,看看也無妨。多一點思路。 分組捕獲 - () 就是用括號把要匹配的內容擴起來 命名分組捕獲 - (?<name>)或(?'
關於正則表示式——捕獲型括號和非捕獲型括號
對於括號中的子表示式,正則表示式會將匹配的子表示式進行儲存。 <pre class="javascript" name="code">var regular = /^Subject:(\d)/ var str = "Subject:1 as something"
JDK7 正則表示式 捕獲組命名
jdk6之前的正則表示式不支援命名捕獲組功能,只能通過捕獲組的索引來訪問捕獲組。當正則表示式比較複雜的時候,裡面含有大量的捕獲組和非捕獲組,通過從左至右數括號來得知捕獲組的計數也是一件很煩人的事情;而且這樣做程式碼的可讀性也不好,當正則表示式需要修改的時候也會改
JavaScript正則表示式分組模式:捕獲性分組與非捕獲性分組及前瞻後顧(斷言)
javascript正則表示式裡分組模式以小括號來()表示分組,例:/([a-z])/ 捕獲性分組:() 捕獲性分組工作模式()會把每個分組裡匹配的值儲存起來。 比如利用捕獲性分組把 hello world 互換成 world hello: 方法一:
java正則表示式捕獲組
Java中使用正則表示式返回符合正則表示式的字串就要用到group(),group中記錄了所有符合指定表示式的字串。本文通過一段程式碼講解如何使用group()。<span style="whi