主頁(yè) > 知識(shí)庫(kù) > 正則表達(dá)式零寬斷言詳解

正則表達(dá)式零寬斷言詳解

熱門(mén)標(biāo)簽:菏澤智能ai電銷(xiāo)機(jī)器人銷(xiāo)售公司 400免費(fèi)電話去哪申請(qǐng) 宿遷智能外呼系統(tǒng)供應(yīng)商 線上教育ai外呼系統(tǒng) 地圖標(biāo)注商戶中心要收錢(qián)多少 鄂州人工智能電銷(xiāo)機(jī)器人軟件 地圖標(biāo)注字母的軟件 css百度地圖標(biāo)注位置顯示 實(shí)用地圖標(biāo)注app

正則表達(dá)式零寬斷言:

零寬斷言是正則表達(dá)式中的難點(diǎn),所以本章節(jié)重點(diǎn)從匹配原理方面進(jìn)行一下分析。零寬斷言還有其他的名稱(chēng),例如"環(huán)視"或者"預(yù)搜索"等等,不過(guò)這些都不是我們關(guān)注的重點(diǎn)。

一.基本概念:

零寬斷言正如它的名字一樣,是一種零寬度的匹配,它匹配到的內(nèi)容不會(huì)保存到匹配結(jié)果中去,最終匹配結(jié)果只是一個(gè)位置而已。
作用是給指定位置添加一個(gè)限定條件,用來(lái)規(guī)定此位置之前或者之后的字符必須滿足限定條件才能使正則中的字表達(dá)式匹配成功。
注意:這里所說(shuō)的子表達(dá)式并非只有用小括號(hào)括起來(lái)的表達(dá)式,而是正則表達(dá)式中的任意匹配單元。
javascript只支持零寬先行斷言,而零寬先行斷言又可以分為正向零寬先行斷言,和負(fù)向零寬先行斷言。

代碼實(shí)例如下:

實(shí)例代碼一:

var str="abZW863";
var reg=/ab(?=[A-Z])/;
console.log(str.match(reg));

在以上代碼中,正則表達(dá)式的語(yǔ)義是:匹配后面跟隨任意一個(gè)大寫(xiě)字母的字符串"ab"。最終匹配結(jié)果是"ab",因?yàn)榱銓挃嘌?(?=[A-Z])"并不匹配任何字符,只是用來(lái)規(guī)定當(dāng)前位置的后面必須是一個(gè)大寫(xiě)字母。

實(shí)例代碼二:

var str="abZW863";
var reg=/ab(?![A-Z])/;
console.log(str.match(reg));

以上代碼中,正則表達(dá)式的語(yǔ)義是:匹配后面不跟隨任意一個(gè)大寫(xiě)字母的字符串"ab"。正則表達(dá)式?jīng)]能匹配任何字符,因?yàn)樵谧址?,ab的后面跟隨有大寫(xiě)字母。

二.匹配原理:

上面代碼只是用概念的方式介紹了零寬斷言是如何匹配的。
下面就以匹配原理的方式分別介紹一下正向零寬斷言和負(fù)向零寬斷言是如何匹配的。
1.正向零寬斷言:
代碼實(shí)例如下:

var str="div>antzone";
var reg=/^(?=)[^>]+>\w+/;
console.log(str.match(reg));

匹配過(guò)程如下:
首先由正則表達(dá)式中的"^"獲取控制權(quán),首先由位置0開(kāi)始進(jìn)行匹配,它匹配開(kāi)始位置0,匹配成功,然后控制權(quán)轉(zhuǎn)交給"(?=)",,由于"^"是零寬的,所以"(?=)"也是從位置0處開(kāi)始匹配,它要求所在的位置右側(cè)必須是字符"",位置0的右側(cè)恰好是字符"",匹配成功,然后控制權(quán)轉(zhuǎn)交個(gè)"",由于"(?=)"也是零寬的,所以它也是從位置0處開(kāi)始匹配,于是匹配成功,后面的匹配過(guò)程就不介紹了。

2.負(fù)向零寬斷言:

代碼實(shí)例如下:

var str="abZW863ab88"; 
var reg=/ab(?![A-Z])/g; 
console.log(str.match(reg));

匹配過(guò)程如下:
首先由正則表達(dá)式的字符"a"獲取控制權(quán),從位置0處開(kāi)始匹配,匹配字符"a"成功,然后控制權(quán)轉(zhuǎn)交給"b",從位置1處開(kāi)始匹配,配字符"b"成功,然后控制權(quán)轉(zhuǎn)交給"(?![A-Z])",它從位置2處開(kāi)始匹配,它要求所在位置的右邊不能夠是任意一個(gè)大寫(xiě)字母,而位置的右邊是大寫(xiě)字母"Z",匹配失敗,然后控制權(quán)又重新交給字符"a",并從位置1處開(kāi)始嘗試,匹配失敗,然后控制權(quán)再次交給字符"a",從位置2處開(kāi)始嘗試匹配,依然失敗,如此往復(fù)嘗試,直到從位置7處開(kāi)始嘗試匹配成功,然后將控制權(quán)轉(zhuǎn)交給"b",然后從位置8處開(kāi)始嘗試匹配,匹配成功,然后再將控制權(quán)轉(zhuǎn)交給"(?![A-Z])",它從位置9處開(kāi)始嘗試匹配,它規(guī)定它所在的位置右邊不能夠是大寫(xiě)字母,匹配成功,但是它并不會(huì)真正匹配字符,所以最終匹配結(jié)果是"ab"。

以下是補(bǔ)充

零寬斷言是正則表達(dá)式中的一種方法,正則表達(dá)式在計(jì)算機(jī)科學(xué)中,是指一個(gè)用來(lái)描述或者匹配一系列符合某個(gè)句法規(guī)則的字符串的單個(gè)字符串。

定義解釋

零寬斷言是正則表達(dá)式中的一種方法
正則表達(dá)式在計(jì)算機(jī)科學(xué)中,是指一個(gè)用來(lái)描述或者匹配一系列符合某個(gè)句法規(guī)則的字符串的單個(gè)字符串。在很多文本編輯器或其他工具里,正則表達(dá)式通常被用來(lái)檢索和/或替換那些符合某個(gè)模式的文本內(nèi)容。許多程序設(shè)計(jì)語(yǔ)言都支持利用正則表達(dá)式進(jìn)行字符串操作。例如,在Perl中就內(nèi)建了一個(gè)功能強(qiáng)大的正則表達(dá)式引擎。正則表達(dá)式這個(gè)概念最初是由Unix中的工具軟件(例如sed和grep)普及開(kāi)的。正則表達(dá)式通??s寫(xiě)成“regex”,單數(shù)有regexp、regex,復(fù)數(shù)有regexps、regexes、regexen。

零寬斷言

用于查找在某些內(nèi)容(但并不包括這些內(nèi)容)之前或之后的東西,也就是說(shuō)它們像\b,^,$那樣用于指定一個(gè)位置,這個(gè)位置應(yīng)該滿足一定的條件(即斷言),因此它們也被稱(chēng)為零寬斷言。最好還是拿例子來(lái)說(shuō)明吧: 斷言用來(lái)聲明一個(gè)應(yīng)該為真的事實(shí)。正則表達(dá)式中只有當(dāng)斷言為真時(shí)才會(huì)繼續(xù)進(jìn)行匹配。

(?=exp)也叫零寬度正預(yù)測(cè)先行斷言,它斷言自身出現(xiàn)的位置的后面能匹配表達(dá)式exp。比如\b(?=re)\w+\b,匹配以re開(kāi)頭的單詞的后面部分(除了re以外的部分),如查找reading a book.時(shí),它會(huì)匹配ading。

var reg = new Regex(@"\w+(?=ing)");
var str = "muing";
Console.WriteLine(reg.Match(str).Value);//返回mu

(?=exp)也叫零寬度正回顧后發(fā)斷言,它斷言自身出現(xiàn)的位置的前面能匹配表達(dá)式exp。比如\b\w+(?=ing\b)會(huì)匹配以ing結(jié)尾的單詞的前半部分(除了ing以外的部分),例如在查找I am reading.時(shí),它匹配read。

假如你想要給一個(gè)很長(zhǎng)的數(shù)字中每三位間加一個(gè)逗號(hào)(當(dāng)然是從右邊加起了),你可以這樣查找需要在前面和里面添加逗號(hào)的部分:((?=\d)\d{3})+\b,用它對(duì)1234567890進(jìn)行查找時(shí)結(jié)果是234567890。
下面這個(gè)例子同時(shí)使用了這兩種斷言:(?=\s)\d+(?=\s)匹配以空白符間隔的數(shù)字(再次強(qiáng)調(diào),不包括這些空白符)。

負(fù)向零寬斷言

前面我們提到過(guò)怎么查找不是某個(gè)字符或不在某個(gè)字符類(lèi)里的字符的方法(反義)。但是如果我們只是想要確保某個(gè)字符沒(méi)有出現(xiàn),但并不想去匹配它時(shí)怎么辦?例如,如果我們想查找這樣的單詞--它里面出現(xiàn)了字母q,但是q后面跟的不是字母u,我們可以嘗試這樣:

\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的單詞。但是如果多做測(cè)試(或者你思維足夠敏銳,直接就觀察出來(lái)了),你會(huì)發(fā)現(xiàn),如果q出現(xiàn)在單詞的結(jié)尾的話,像Iraq,Benq,這個(gè)表達(dá)式就會(huì)出錯(cuò)。這是因?yàn)閇^u]總要匹配一個(gè)字符,所以如果q是單詞的最后一個(gè)字符的話,后面的[^u]將會(huì)匹配q后面的單詞分隔符(可能是空格,或者是句號(hào)或其它的什么),后面的\w*\b將會(huì)匹配下一個(gè)單詞,于是\b\w*q[^u]\w*\b就能匹配整個(gè)Iraq fighting。負(fù)向零寬斷言能解決這樣的問(wèn)題,因?yàn)樗黄ヅ湟粋€(gè)位置,并不消費(fèi)任何字符?,F(xiàn)在,我們可以這樣來(lái)解決這個(gè)問(wèn)題:\b\w*q(?!u)\w*\b。

零寬度負(fù)預(yù)測(cè)先行斷言(?!exp),斷言此位置的后面不能匹配表達(dá)式exp。例如:\d{3}(?!\d)匹配三位數(shù)字,而且這三位數(shù)字的后面不能是數(shù)字;\b((?!abc)\w)+\b匹配不包含連續(xù)字符串a(chǎn)bc的單詞。
同理,我們可以用(?!exp),零寬度負(fù)回顧后發(fā)斷言來(lái)斷言此位置的前面不能匹配表達(dá)式exp:(?![a-z])\d{7}匹配前面不是小寫(xiě)字母的七位數(shù)字。

一個(gè)更復(fù)雜的例子:(?=(\w+)>).*(?=\/\1>)匹配不包含屬性的簡(jiǎn)單HTML標(biāo)簽內(nèi)里的內(nèi)容。(?=(\w+)>)指定了這樣的前綴:被尖括號(hào)括起來(lái)的單詞(比如可能是b>),然后是.*(任意的字符串),最后是一個(gè)后綴(?=\/\1>)。注意后綴里的\/,它用到了前面提過(guò)的字符轉(zhuǎn)義;\1則是一個(gè)反向引用,引用的正是捕獲的第一組,前面的(\w+)匹配的內(nèi)容,這樣如果前綴實(shí)際上是b>的話,后綴就是/b>了。整個(gè)表達(dá)式匹配的是b>和/b>之間的內(nèi)容(再次提醒,不包括前綴和后綴本身)。

上面的看了有點(diǎn)傷腦筋啊。下面來(lái)點(diǎn)補(bǔ)充一

斷言用來(lái)聲明一個(gè)應(yīng)該為真的事實(shí)。正則表達(dá)式中只有當(dāng)斷言為真時(shí)才會(huì)繼續(xù)進(jìn)行匹配。
接下來(lái)的四個(gè)用于查找在某些內(nèi)容(但并不包括這些內(nèi)容)之前或之后的東西,也就是說(shuō)它們像\b,^,$那樣用于指定一個(gè)位置,這個(gè)位置應(yīng)該滿足一定的條件(即斷言),因此它們也被稱(chēng)為零寬斷言。最好還是拿例子來(lái)說(shuō)明吧:

(?=exp)也叫零寬度正預(yù)測(cè)先行斷言,它斷言自身出現(xiàn)的位置的后面能匹配表達(dá)式exp。比如\b\w+(?=ing\b),匹配以ing結(jié)尾的單詞的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.時(shí),它會(huì)匹配sing和danc。
(?=exp)也叫零寬度正回顧后發(fā)斷言,它斷言自身出現(xiàn)的位置的前面能匹配表達(dá)式exp。比如(?=\bre)\w+\b會(huì)匹配以re開(kāi)頭的單詞的后半部分(除了re以外的部分),例如在查找reading a book時(shí),它匹配ading。

假如你想要給一個(gè)很長(zhǎng)的數(shù)字中每三位間加一個(gè)逗號(hào)(當(dāng)然是從右邊加起了),你可以這樣查找需要在前面和里面添加逗號(hào)的部分:((?=\d)\d{3})*\b,用它對(duì)1234567890進(jìn)行查找時(shí)結(jié)果是234567890。
下面這個(gè)例子同時(shí)使用了這兩種斷言:(?=\s)\d+(?=\s)匹配以空白符間隔的數(shù)字(再次強(qiáng)調(diào),不包括這些空白符)。

補(bǔ)充二:

最近為了對(duì)html文件進(jìn)行源碼處理,需要進(jìn)行正則查找并替換。于是借著這個(gè)機(jī)會(huì)把正則系統(tǒng)地學(xué)一下,雖然以前也用過(guò)正則,但每次都是臨時(shí)學(xué)一下混過(guò)關(guān)的。在學(xué)習(xí)的過(guò)程中還是遇到不少問(wèn)題的,特別是零寬斷言(這里還要吐槽下,網(wǎng)上到處都是都復(fù)制粘貼的內(nèi)容,遇到個(gè)問(wèn)題查看了不少重復(fù)的東西,汗?。。。栽谶@里把自己的理解寫(xiě)下來(lái),方便以后查閱!

      零寬度正預(yù)測(cè)先行斷言是什么呢,看msdn上的官方解釋定義

(?= 子表達(dá)式)

(零寬度正預(yù)測(cè)先行斷言。)僅當(dāng)子表達(dá)式在此位置的右側(cè)匹配時(shí)才繼續(xù)匹配。例如,\w+(?=\d) 與后跟數(shù)字的單詞匹配,而不與該數(shù)字匹配。

      經(jīng)典的例子:某單詞以ing結(jié)尾,要獲取ing前面的內(nèi)容

var reg = new Regex(@"\w+(?=ing)");
var str = "muing";
Console.WriteLine(reg.Match(str).Value);//返回mu

      以上是網(wǎng)上到處可見(jiàn)的例子,到這里或許你明白了,原來(lái)就是返回了exp表達(dá)式前面的內(nèi)容。

     再看下面的的代碼

var reg = new Regex(@"a(?=b)c");
var str = "abc";
Console.WriteLine(reg.IsMatch(str));//返回false

      為什么會(huì)返回false?

     其實(shí)msdn官方定義已經(jīng)說(shuō)了,只是它說(shuō)得很官方而已。這里需要我們注意一個(gè)關(guān)鍵點(diǎn):此位置。沒(méi)錯(cuò),是位置而不是字符。那么結(jié)合官方定義和第一個(gè)例子來(lái)理解第二個(gè)例子:

     因?yàn)閍后面是b,則此時(shí)返回了匹配內(nèi)容a(由第一個(gè)例子知道,只返回a不返回exp匹配的內(nèi)容),此時(shí)a(?=b)c中的a(?=b)部分已經(jīng)解決了,接下來(lái)要解決c的匹配問(wèn)題了,此時(shí)匹配c要從字符串a(chǎn)bc哪里開(kāi)始呢,結(jié)合官方定義,就知道是從子表達(dá)的位置向右開(kāi)始的,那么就是從b的位置開(kāi)始,但b又不匹配a(?=b)c剩余部分的c,所以abc就不匹配a(?=b)c了。

     那么如果要上面的進(jìn)行匹配,正則應(yīng)該如何寫(xiě)呢?

     答案是:a(?=b)bc

     當(dāng)然,有人會(huì)說(shuō)直接abc就匹配上了,還要這么折騰嗎?當(dāng)然不用這么折騰,只是為了說(shuō)明零寬度正預(yù)測(cè)先行斷言到底是怎么一回事?關(guān)于其它的零寬斷言也是同一原理!

補(bǔ)充三

(?=exp):零寬度正預(yù)測(cè)先行斷言,它斷言自身出現(xiàn)的位置的后面能匹配表達(dá)式exp。

#匹配后面為_(kāi)path,結(jié)果為product
  'product_path'.scan /(product)(?=_path)/

(?=exp):零寬度正回顧后發(fā)斷言,它斷言自身出現(xiàn)的位置的前面能匹配表達(dá)式exp

#匹配前面為name:,結(jié)果為wangfei
'name:wangfei'.scan /(?=name:)(wangfei)/ #wangfei

(?!exp):零寬度負(fù)預(yù)測(cè)先行斷言,斷言此位置的后面不能匹配表達(dá)式exp。

#匹配后面不是_path
'product_path'.scan /(product)(?!_path)/  #nil
#匹配后面不是_url
'product_path'.scan /(product)(?!_url)/  #product

(?!exp):零寬度負(fù)回顧后發(fā)斷言來(lái)斷言此位置的前面不能匹配表達(dá)式exp

#匹配前面不是name:
'name:angelica'.scan /(?!name:)(angelica)/  #nil
#匹配前面不是nick_name:
'name:angelica'.scan /(?!nick_name:)(angelica)/#angelica

小編也受夠了這個(gè)東西,等有好的東西再分享,今天洗洗睡吧

您可能感興趣的文章:
  • 正則表達(dá)式中環(huán)視的簡(jiǎn)單應(yīng)用示例【基于java】
  • 正則應(yīng)用之 逆序環(huán)視探索 .
  • 正則匹配原理之 逆序環(huán)視深入 .
  • 正則基礎(chǔ)之 環(huán)視 Lookaround
  • javascript 正則表達(dá)式分組、斷言詳解
  • 正則表達(dá)式之零寬斷言實(shí)例詳解【基于PHP】
  • 正則表達(dá)式斷言、巡視(Assertions)、正向斷言、反向斷言介紹
  • 正則表達(dá)式環(huán)視概念與用法分析

標(biāo)簽:鞍山 池州 綿陽(yáng) 三亞 恩施 六安 梅州 咸陽(yáng)

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《正則表達(dá)式零寬斷言詳解》,本文關(guān)鍵詞  正則,表達(dá)式,零寬,斷言,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《正則表達(dá)式零寬斷言詳解》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于正則表達(dá)式零寬斷言詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 企业400电话

    智能AI客服机器人
    15000

    在线订购

    合计11份范本:公司章程+合伙协议+出资协议+合作协议+股权转让协议+增资扩股协议+股权激励+股东会决议+董事会决议

    推薦文章