亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Regex > 正文

正則基礎之 環視 Lookaround

2020-03-16 21:16:28
字體:
來源:轉載
供稿:網友
環視只進行子表達式的匹配,不占有字符,匹配到的內容不保存到最終的匹配結果,是零寬度的。環視匹配的最終結果就是一個位置。
 
 

1       環視基礎

環視只進行子表達式的匹配,不占有字符,匹配到的內容不保存到最終的匹配結果,是零寬度的。環視匹配的最終結果就是一個位置。

環視的作用相當于對所在位置加了一個附加條件,只有滿足這個條件,環視子表達式才能匹配成功。

環視按照方向劃分有順序和逆序兩種,按照是否匹配有肯定和否定兩種,組合起來就有四種環視。順序環視相當于在當前位置右側附加一個條件,而逆序環視相當于在當前位置左側附加一個條件。

表達式

說明

(?<=Expression)

逆序肯定環視,表示所在位置左側能夠匹配Expression

(?<!Expression)

逆序否定環視,表示所在位置左側不能匹配Expression

(?=Expression)

順序肯定環視,表示所在位置右側能夠匹配Expression

(?!Expression)

順序否定環視,表示所在位置右側不能匹配Expression

 對于環視的叫法,有的文檔里叫預搜索,有的叫什么什么斷言的,這里使用了更多人容易接受的《精通正則表達式》中“環視”的叫法,其實叫什么無所謂,只要知道是什么作用就是了,就這么幾個語法規則, 還是很容易記的

2       環視匹配原理

 環視是正則中的一個難點,對于環視的理解,可以從應用和原理兩個角度理解,如果想理解得更清晰、深入一些,還是從原理的角度理解好一些,正則匹配基本原理參考 NFA引擎匹配原理。

上面提到環視相當于對“所在位置”附加了一個條件,環視的難點在于找到這個“位置”,這一點解決了,環視也就沒什么秘密可言了。

順序環視匹配過程

對于順序肯定環視(?=Expression)來說,當子表達式Expression匹配成功時,(?=Expression)匹配成功,并報告(?=Expression)匹配當前位置成功。

對于順序否定環視(?!Expression)來說,當子表達式Expression匹配成功時,(?!Expression)匹配失??;當子表達式Expression匹配失敗時,(?!Expression)匹配成功,并報告(?!Expression)匹配當前位置成功;

順序肯定環視的例子已在NFA引擎匹配原理中講解過了,這里再講解一下順序否定環視。

 

正則基礎之 環視 Lookaround

源字符串:aa<p>one</p>bb<div>two</div>cc

正則表達式:<(?!/?p/b)[^>]+>

這個正則的意義就是匹配除<p…>或</p>之外的其余標簽。

匹配過程:

正則基礎之 環視 Lookaround

首先由字符“<”取得控制權,從位置0開始匹配,由于“<”匹配“a”失敗,在位置0處整個表達式匹配失敗,第一次迭代匹配失敗,正則引擎向前傳動,由位置1處開始嘗試第二次迭代匹配。

重復以上過程,直到位置2,“<”匹配“<”成功,控制權交給“(?!/?p/b)”;“(?!/?p/b)”子表達式取得控制權后,進行內部子表達式的匹配。首先由“/?”取得控制權,嘗試匹配“p”失敗,進行回溯,不匹配,控制權交給“p”;由“p”來嘗試匹配“p”,匹配成功,控制權交給“/b”;由“/b”來嘗試匹配位置4,匹配成功。此時子表達式匹配完成,“/?p/b”匹配成功,那么環視表達式“(?!/?p/b)”就匹配失敗。在位置2處整個表達式匹配失敗,新一輪迭代匹配失敗,正則引擎向前傳動,由位置3處開始嘗試下一輪迭代匹配。

在位置8處也會遇到一輪“/?p/b”匹配“/p”成功,而導致環視表達式“(?!/?p/b)”匹配失敗,從而導致整個表達式匹配失敗的過程。

重復以上過程,直到位置14,“<”匹配“<”成功,控制權交給“(?!/?p/b)”;“/?”嘗試匹配“d”失敗,進行回溯,不匹配,控制權交給“p”;由“p”來嘗試匹配“d”,匹配失敗,已經沒有備選狀態可供回溯,匹配失敗。此時子表達式匹配完成,“/?p/b”匹配失敗,那么環視表達式“(?!/?p/b)”就匹配成功。匹配的結果是位置15,然后控制權交給“[^>]+”;由“[^>]+”從位置15進行嘗試匹配,可以成功匹配到“div”,控制權交給“>”;由“>”來匹配“>”。

此時正則表達式匹配完成,報告匹配成功。匹配結果為“<div>”,開始位置為14,結束位置為19。其中“<”匹配“<”,“(?!/?p/b)”匹配位置15,“[^>]+”匹配字符串“div”,“>”匹配“>”。

逆序環視基礎

對于逆序肯定環視(?<=Expression)來說,當子表達式Expression匹配成功時,(?<=Expression)匹配成功,并報告(?<=Expression)匹配當前位置成功。

對于逆序否定環視(?<!Expression)來說,當子表達式Expression匹配成功時,(?<!Expression)匹配失??;當子表達式Expression匹配失敗時,(?<!Expression)匹配成功,并報告(?<!Expression)匹配當前位置成功;

順序環視相當于在當前位置右側附加一個條件,所以它的匹配嘗試是從當前位置開始的,然后向右嘗試匹配,直到某一位置使得匹配成功或失敗為止。而逆序環視的特殊處在于,它相當于在當前位置左側附加一個條件,所以它不是在當前位置開始嘗試匹配的,而是從當前位置左側某一位置開始,匹配到當前位置為止,報告匹配成功或失敗。

順序環視嘗試匹配的起點是確定的,就是當前位置,而匹配的終點是不確定的。逆序環視匹配的起點是不確定的,是當前位置左側某一位置,而匹配的終點是確定的,就是當前位置。

所以順序環視相對是簡單的,而逆序環視相對是復雜的。這也就是為什么大多數語言和工具都提供了對順序環視的支持,而只有少數語言提供了對逆序環視支持的原因。

JavaScript中只支持順序環視,不支持逆序環視。

Java中雖然順序環視和逆序環視都支持,但是逆序環視只支持長度確定的表達式,逆序環視中量詞只支持“?”,不支持其它長度不定的量詞。長度確定時,引擎可以向左查找固定長度的位置作為起點開始嘗試匹配,而如果長度不確定時,就要從位置0開始嘗試匹配,處理的復雜度是顯而易見的。

目前只有.NET中支持不確定長度的逆序環視。

逆序環視匹配過程

正則基礎之 環視 Lookaround

源字符串:<div>a test</div>

正則表達式:(?<=<div>)[^<]+(?=</div>)

這個正則的意義就是匹配<div>和</div>標簽之間的內容,而不包括<div>和</div>標簽本身。

匹配過程:

首先由“(?<=<div>)”取得控制權,從位置0開始匹配,由于位置0是起始位置,左側沒有任何內容,所以“<div>”必然匹配失敗,從而環視表達式“(?<=<div>)”匹配失敗,導致整個表達式在位置0處匹配失敗。第一輪迭代匹配失敗,正則引擎向前傳動,由位置1處開始嘗試第二次迭代匹配。

直到傳動到位置5,“(?<=<div>)”取得控制權,向左查找5個位置,由位置0開始匹配,由“<div>”匹配“<div>”成功,從而“(?<=<div>)”匹配成功,匹配的結果為位置5,控制權交給“[^<]+”;“[^<]+”從位置5開始嘗試匹配,匹配“a test”成功,控制權交給“(?=</div>)”;由“</div>”匹配“</div>”成功,從而“(?=</div>)”匹配成功,匹配結果為位置11。

此時正則表達式匹配完成,報告匹配成功。匹配結果為“a test”,開始位置為5,結束位置為11。其中“(?<=<div>)”匹配位置5,“[^<]+”匹配“a test”,“(?=</div>)”匹配位置11。

逆序否定環視的匹配過程與上述過程類似,區別只是當Expression匹配失敗時,逆序否定表達式(?<!Expression)才匹配成功。

到此環視的匹配原理已基本講解完,環視也就沒有什么秘密可言了,所需要的,也只是多加練習而已。

3       環視應用

今天寫累了,暫時就給出一個環視的綜合應用實例吧,至于環視的應用場景和技巧,后面再整理。

需求:數字格式化成用“,”的貨幣格式。

正則表達式:(?<=/d)(?<!/./d*)(?=(?:/d{3})+(?:/./d+|$))

測試代碼:

double[] data = new double[] { 0, 12, 123, 1234, 12345, 123456, 1234567, 123456789, 1234567890, 12.345, 123.456, 1234.56, 12345.6789, 123456.789, 1234567.89, 12345678.9 };

foreach (double d in data)

{

    richTextBox2.Text += "源字符串:" + d.ToString().PadRight(15) + "格式化:" + Regex.Replace(d.ToString(), @"(?<=/d)(?<!/./d*)(?=(?:/d{3})+(?:/./d+|$))", ",") + "/n";

}

輸出結果:

源字符串:0              格式化:0

源字符串:12             格式化:12

源字符串:123            格式化:123

源字符串:1234           格式化:1,234

源字符串:12345          格式化:12,345

源字符串:123456         格式化:123,456

源字符串:1234567        格式化:1,234,567

源字符串:123456789      格式化:123,456,789

源字符串:1234567890     格式化:1,234,567,890

源字符串:12.345         格式化:12.345

源字符串:123.456        格式化:123.456

源字符串:1234.56        格式化:1,234.56

源字符串:12345.6789     格式化:12,345.6789

源字符串:123456.789     格式化:123,456.789

源字符串:1234567.89     格式化:1,234,567.89

源字符串:12345678.9     格式化:12,345,678.9

實現分析:

首先根據需求可以確定是把一些特定的位置替換為“,”,接下來就是分析并找到這些位置的規律,并抽象出來以正則表達式來表示。

1、   這個位置的左側必須為數字

2、   這個位置右側到出現“.”或結尾為止,必須是數字,且數字的個數必須為3的倍數

3、   這個位置左側相隔任意個數字不能出現“.”

由以上三條,就可以完全確定這些位置,只要實現以上三條,組合一下正則表達式就可以了。

根據分析,最終匹配的結果是一個位置,所以所有子表達式都要求是零寬度。

1、   是對當前所在位置左側附加的條件,所以要用到逆序環視,因為要求必須出現,所以是肯定的,符合這一條件的子表達式即為“(?<=/d)

2、   是對當前所在位置右側附加的條件,所以要用到順序環視,也是要求出現,所以是肯定的,是數字,且個數為3的倍數,即“(?=(?:/d{3})*)”,到出現“.”或結尾為止,即“(?=(?:/d{3})*(?:/.|$))

3、   是對當前所在位置左側附加的條件,所以要用到逆序環視,因為要求不能出現,所以是否定的,即“(?<!/./d*)

因為零寬度的子表達式是非互斥的,最后匹配的都是同一個位置,所以先后順序是不影響最后的匹配結果的,可以任意組合,只是習慣上把逆序環視寫在左側,順序環視寫在右側。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品成人久久电影| 亚洲欧美三级伦理| 欧美激情乱人伦一区| 2023亚洲男人天堂| 国产午夜精品麻豆| 精品女同一区二区三区在线播放| 粉嫩老牛aⅴ一区二区三区| 亚洲欧美成人精品| 国产成人综合一区二区三区| 欧美在线www| 欧美精品激情视频| 亚洲大尺度美女在线| 国产亚洲精品一区二555| 国产成+人+综合+亚洲欧美丁香花| 亚洲精品福利视频| 亚洲精品aⅴ中文字幕乱码| 亚洲国产精品va| 国产一区二区三区在线免费观看| 亚洲激情成人网| 91精品久久久久久久久| 精品毛片三在线观看| 欧美激情精品久久久久久蜜臀| 亚洲精品久久久久中文字幕欢迎你| 欧美孕妇与黑人孕交| 色中色综合影院手机版在线观看| 欧美华人在线视频| 欧美激情a∨在线视频播放| www日韩中文字幕在线看| 日韩免费观看视频| 成人性生交大片免费看小说| 国产精品专区h在线观看| 久久久久久av| 欧美黑人又粗大| 九九视频直播综合网| 中文字幕精品在线视频| 久久久久久91香蕉国产| 国产一区二区三区三区在线观看| 国产精品第三页| 国产日韩在线亚洲字幕中文| 一区二区三区无码高清视频| 国产亚洲精品成人av久久ww| 日本免费久久高清视频| 亚洲日本中文字幕| 成人中文字幕+乱码+中文字幕| 久久影视电视剧免费网站清宫辞电视| 一区二区日韩精品| 久久国产精品久久国产精品| 深夜福利日韩在线看| 日本精品免费观看| 久久精品色欧美aⅴ一区二区| 91高清在线免费观看| 亚洲白拍色综合图区| 另类美女黄大片| 日韩免费av一区二区| 色婷婷成人综合| 日韩一区视频在线| 国自产精品手机在线观看视频| 国产精品观看在线亚洲人成网| 隔壁老王国产在线精品| 日韩在线视频免费观看| 国产精品自产拍在线观看中文| 久久99久久亚洲国产| 日韩中文字幕在线看| 一区二区亚洲欧洲国产日韩| 日韩电影中文字幕一区| 97在线视频免费观看| 亚洲天堂成人在线视频| 国外日韩电影在线观看| 欧美激情欧美狂野欧美精品| 欧美老女人xx| 一二美女精品欧洲| 97欧美精品一区二区三区| 中文字幕日本精品| 日韩中文字幕网| 97国产一区二区精品久久呦| 丁香五六月婷婷久久激情| 亚洲欧洲在线免费| 97超级碰碰人国产在线观看| 18一19gay欧美视频网站| 成人黄色免费网站在线观看| 久热精品视频在线| 91精品国产沙发| 欧美精品在线免费观看| 91精品国产自产在线老师啪| 97视频色精品| 91福利视频在线观看| 国产亚洲综合久久| 深夜精品寂寞黄网站在线观看| 国产精品网红福利| www.久久草.com| 日韩av大片免费看| 日韩国产一区三区| 久久亚洲综合国产精品99麻豆精品福利| 一本一本久久a久久精品牛牛影视| 亚洲男人av在线| 国产日韩中文字幕在线| 国产亚洲美女精品久久久| 亚洲一二在线观看| 好吊成人免视频| 日韩美女福利视频| 久久精品影视伊人网| 福利视频导航一区| 欧美极品美女视频网站在线观看免费| 久久在线观看视频| 国产一区红桃视频| 免费不卡在线观看av| 国产成人极品视频| 久久香蕉国产线看观看av| 久久99久国产精品黄毛片入口| 最近中文字幕mv在线一区二区三区四区| 亚洲男女性事视频| 亚洲成在人线av| 国产亚洲aⅴaaaaaa毛片| www亚洲欧美| 欧美韩国理论所午夜片917电影| 日韩中文字幕免费视频| 国产欧美亚洲精品| 国产亚洲精品综合一区91| 中国日韩欧美久久久久久久久| 中文字幕一区日韩电影| 成人在线视频福利| 亚洲精品黄网在线观看| 国产日韩视频在线观看| 久久91精品国产91久久久| 日韩小视频在线观看| 国产精品一区二区三区在线播放| 亚洲欧美在线x视频| 久久福利视频导航| 黄色成人av网| 韩曰欧美视频免费观看| 亚洲欧美精品中文字幕在线| 色无极影院亚洲| 国产美女久久精品香蕉69| 亚洲男人天堂网| 热久久视久久精品18亚洲精品| 91精品美女在线| 精品激情国产视频| 国产精品高潮在线| 欧美日本黄视频| 亚洲大尺度美女在线| 久久成人免费视频| 一本色道久久88亚洲综合88| 不卡伊人av在线播放| 黑人极品videos精品欧美裸| 欧美视频不卡中文| 中文字幕av一区二区| 欧美黄色片免费观看| 操人视频在线观看欧美| 亚洲成人激情在线观看| 一二美女精品欧洲| 欧美性xxxx极品高清hd直播| 精品欧美国产一区二区三区| 在线精品国产成人综合| 亚洲精品国产精品自产a区红杏吧| 欧美黑人xxx| 久久视频精品在线| 日日噜噜噜夜夜爽亚洲精品| 色妞色视频一区二区三区四区| 91沈先生在线观看| 伊人久久大香线蕉av一区二区| 欧美激情视频免费观看| 久久久国产一区二区三区| 国产成人自拍视频在线观看| 成人免费淫片视频软件|