欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET正則基礎(chǔ)之.NET正則匹配模式

 更新時(shí)間:2023年05月28日 14:14:39   作者:過(guò)客  
匹配模式指的是一些可以改變正則表達(dá)式匹配行為的選項(xiàng)或修飾符。不同的語(yǔ)言支持的匹配模式不同,使用的方式也不同,需要的朋友可以參考下

1、概述

匹配模式指的是一些可以改變正則表達(dá)式匹配行為的選項(xiàng)或修飾符。不同的語(yǔ)言支持的匹配模式不同,使用的方式也不同。

一般可分為全局和內(nèi)聯(lián)兩種。下面主要介紹.NET中的匹配模式,其它語(yǔ)言的匹配模式,后續(xù)視情況補(bǔ)充。

2、匹配模式

2.1全局匹配模式和內(nèi)聯(lián)匹配模式概述

.NET中的全局匹配模式是通過(guò)RegexOptions 枚舉值指定的,可以按位“或”進(jìn)行組合,全局匹配模式只能作用于整個(gè)正則表達(dá)式。全局匹配模式提供的模式更多,可以靈活的動(dòng)態(tài)指定匹配模式。

而內(nèi)聯(lián)匹配模式是通過(guò)在正則表達(dá)式中,使用(?imnsx-imnsx:)或(?imnsx-imnsx)的分組構(gòu)造來(lái)改變正則表達(dá)式的匹配行為的。內(nèi)聯(lián)匹配模式更靈活、簡(jiǎn)潔,但是提供的模式較少。

下表摘自MSDN,部分說(shuō)明做了修改。

RegexOption 成員

內(nèi)聯(lián)字符

說(shuō)明

None

N/A

指定不設(shè)置任何選項(xiàng)。

IgnoreCase

i

指定不區(qū)分大小寫的匹配。

Multiline

m

指定多行模式。更改 ^ 和 $ 的含義,以使它們分別與任何行的開(kāi)頭和結(jié)尾匹配,而不只是與整個(gè)字符串的開(kāi)頭和結(jié)尾匹配。

ExplicitCapture

n

指定唯一有效的捕獲是顯式命名或編號(hào)的 (?<name>…) 形式的組。這允許圓括號(hào)充當(dāng)非捕獲組,從而避免了由 (?:…) 導(dǎo)致的語(yǔ)法上的笨拙。

Compiled

N/A

指定正則表達(dá)式將被編譯為程序集。生成該正則表達(dá)式的 Microsoft 中間語(yǔ)言 (MSIL) 代碼;以較長(zhǎng)的啟動(dòng)時(shí)間為代價(jià),得到更快的執(zhí)行速度。

Singleline

s

指定單行模式。更改句點(diǎn)字符 (.) 的含義,以使它與每個(gè)字符(而不是除 \n 之外的所有字符)匹配。

IgnorePatternWhitespace

x

指定從模式中排除非轉(zhuǎn)義空白并啟用數(shù)字符號(hào) (#) 后面的注釋。請(qǐng)注意,空白永遠(yuǎn)不會(huì)從字符類中消除。

RightToLeft

N/A

指定搜索是從右向左而不是從左向右進(jìn)行的。具有此選項(xiàng)的正則表達(dá)式將移動(dòng)到起始位置的左邊而不是右邊。

ECMAScript

N/A

指定已為表達(dá)式啟用了符合 ECMAScript 的行為。此選項(xiàng)僅可與 IgnoreCase 和 Multiline 標(biāo)志一起使用。將 ECMAScript 同任何其他標(biāo)志一起使用將導(dǎo)致異常。

CultureInvariant

N/A

指定忽略語(yǔ)言中的區(qū)域性差異。

2.2全局匹配模式

下面根據(jù)各種模式使用的頻率進(jìn)行講解。

2.2.1 IgnoreCase 忽略大小寫

幾乎所有支持正則的語(yǔ)言中都提供了這一模式,是應(yīng)用最多的模式之一,同時(shí)也是被“濫”用最多的模式之一。

開(kāi)啟忽略大小寫模式,則字符可以同時(shí)匹配大寫或小寫形式。比如在此模式下,正則表達(dá)式“<br>”可同時(shí)匹配“<br>”和“<BR>”

但并不是所有的字符都有大小寫形式,所以在書寫的正則中,如果不存在可區(qū)分大小寫形式的元字符或是字符序列時(shí),開(kāi)啟這一模式是沒(méi)有任何意義的。

比如替換一般的html標(biāo)簽的正則表達(dá)式

string result = Regex.Replace(srcStr, @"<[^>]*>", "", RegexOptions.IgnoreCase);

因?yàn)?lt;[^>]*>沒(méi)有哪一個(gè)元字符或是字符序列具有大小寫形式,所以這里的RegexOptions.IgnoreCase是多余的,用在這里雖然不會(huì)改變匹配結(jié)果,但是會(huì)降低匹配效率,同時(shí)這也不是一個(gè)好的習(xí)慣。

只有在正則表達(dá)式中,注意是正則表達(dá)式中,而不是待匹配的源字符串中,涉及到大小寫形式的元字符或是字符序列時(shí),才使用IgnoreCase模式。

2.2.2  Multiline 多行模式

多行模式改變的是“^”和“$”的匹配行為,使“^”和“$”不僅可以匹配整個(gè)字符串的開(kāi)始和結(jié)束位置,還可以匹配每行的開(kāi)始和結(jié)束位置。

首先說(shuō)明一下“行”的范圍。雖然我們?cè)诔绦蛑辛?xí)慣用“\r\n”來(lái)表示換行,但實(shí)際上“\r”和“\n”是不相關(guān)的兩個(gè)字符,一個(gè)表示回車,一個(gè)表示換行。由于歷史原因,“\r”并不是所有系統(tǒng)都支持的,所以“行”是由“\n”來(lái)分割的,其中“\n”屬于前一“行”,而不屬于后一“行”。

舉例來(lái)說(shuō),字符串“a\r\nbc\r\n”共有三行,“a\r\n”為一行,“bc\r\n”為一行,最后還有一個(gè)“”空行。

2.2.2.1  在不開(kāi)啟多行模式情況下,“^”和“$”匹配范圍

“^”的匹配范圍

MatchCollection?mc =?Regex.Matches("a\r\nbc\r\n",?@"^");
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text +=?"匹配內(nèi)容:"?+ m.Value +?"??匹配開(kāi)始索引:"?+ m.Index +?"??匹配長(zhǎng)度:"?+ m.Length +?"\n";
}
/*--------輸出--------
匹配內(nèi)容:??匹配開(kāi)始索引:0??匹配長(zhǎng)度:0
*/

“$”的匹配范圍

MatchCollection?mc =?Regex.Matches("a\r\nbc\r\n",?@"$");
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text +=?"匹配內(nèi)容:"?+ m.Value +?"??匹配開(kāi)始索引:"?+ m.Index +?"??匹配長(zhǎng)度:"?+ m.Length +?"\n";
}
/*--------輸出--------
匹配內(nèi)容:??匹配開(kāi)始索引:6??匹配長(zhǎng)度:0
匹配內(nèi)容:??匹配開(kāi)始索引:7??匹配長(zhǎng)度:0
*/

注意:這里需要注意的是,在沒(méi)有開(kāi)啟多行模式時(shí),字符串結(jié)尾如果是“\n”,那么“$”是可以匹配兩個(gè)位置的,一個(gè)是“\n”前的位置,一個(gè)是字符串結(jié)束位置。字符串結(jié)尾如果不是“\n”,那么“$”就只匹配字符串結(jié)束位置。

MatchCollection?mc =?Regex.Matches("a\r\nbc\r",?@"$");
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text +=?"匹配內(nèi)容:"?+ m.Value +?"??匹配開(kāi)始索引:"?+ m.Index +?"??匹配長(zhǎng)度:"?+ m.Length +?"\n";
}
/*--------輸出--------
匹配內(nèi)容:??匹配開(kāi)始索引:6??匹配長(zhǎng)度:0
*/

2.2.2.2  在開(kāi)啟了多行模式后,“^”和“$”匹配范圍

“^”的匹配范圍

MatchCollection?mc =?Regex.Matches("a\r\nbc\r\n",?@"^",?RegexOptions.Multiline);
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text +=?"匹配內(nèi)容:"?+ m.Value +?"??匹配開(kāi)始索引:"?+ m.Index +?"??匹配長(zhǎng)度:"?+ m.Length +?"\n";
}
/*--------輸出--------
匹配內(nèi)容:??匹配開(kāi)始索引:0??匹配長(zhǎng)度:0
匹配內(nèi)容:??匹配開(kāi)始索引:3??匹配長(zhǎng)度:0
匹配內(nèi)容:??匹配開(kāi)始索引:7??匹配長(zhǎng)度:0
*/

“$”的匹配范圍

MatchCollection?mc =?Regex.Matches("a\r\nbc\r\n",?@"$",?RegexOptions.Multiline);
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text +=?"匹配內(nèi)容:"?+ m.Value +?"??匹配開(kāi)始索引:"?+ m.Index +?"??匹配長(zhǎng)度:"?+ m.Length +?"\n";
}
/*--------輸出--------
匹配內(nèi)容:??匹配開(kāi)始索引:2??匹配長(zhǎng)度:0
匹配內(nèi)容:??匹配開(kāi)始索引:6??匹配長(zhǎng)度:0
匹配內(nèi)容:??匹配開(kāi)始索引:7??匹配長(zhǎng)度:0
*/

2.2.2.3  匹配結(jié)果分析

“^”匹配結(jié)果分析

在不開(kāi)啟多行模式時(shí),“^”只匹配字符串的開(kāi)始位置,也就是位置0。

在開(kāi)啟了多行模式后,“^”匹配字符串開(kāi)始位置和每個(gè)“\n”之后的行起始位置。

“$”匹配結(jié)果分析

在不開(kāi)啟多行模式時(shí),如果字符結(jié)尾是“\n”,那么“$”會(huì)匹配結(jié)尾“\n”之前和結(jié)束兩個(gè)位置。

在開(kāi)啟多行模式后,“$”匹配每行“\n”之前的位置和字符串結(jié)束位置。

需要注意的是,在.NET中,無(wú)論是否開(kāi)啟多行模式,“^”和“$”匹配的都只是一個(gè)位置,是零寬度的。其它語(yǔ)言中“^”和“$”的意義可能會(huì)有所不同。

只有在正則表達(dá)式中涉及到多行的“^”和“$”的匹配時(shí),才使用Multiline模式。

2.2.2.4  應(yīng)用舉例

典型應(yīng)用一(參考 正則中加字符的問(wèn)題):

需求描述:

fffffffffff

fffffffffff

dfdfdfdf

erererere

ferewfdfds

每行后面加一個(gè)“ttt”,即為

fffffffffffttt

fffffffffffttt

dfdfdfdfttt

ererererettt

ferewfdfdsttt

代碼實(shí)現(xiàn):

string result = Regex.Replace(yourStr, @"^.*$", "$0ttt", RegexOptions.Multiline);

典型應(yīng)用二

需求描述:

源字符串

CODE39/CODE93:

A-Z

space,-,.,$,/,+,%

CODE128A:

A-Z

0-9

space,!,",#,$,%,&,…,(,)*,+,逗號(hào),-,.,/, <,=,>,?,@,[,],^,_

CODE128B:

A-Z

a-z

0-9

space,!,",#,$,%,&,…,(,)*,+,逗號(hào),-,.,/, <,=,>,?,@,[,],^,_,{,},|,~

CODE2of5:

0-9

說(shuō)明:

CODE128A:->條碼類別

A-Z

0-9

space,!,",#,$,%,&,…,(,)*,+,逗號(hào),-,.,/, <,=,>,?,@,[,],^,_->表示范圍

要求分別匹配出條碼類別和表示范圍

代碼實(shí)現(xiàn):

MatchCollection?mc =?Regex.Matches(yourStr,?@"(?<type>[^\n:]+):\s*(?<range>(^(?!\s*$).*$\n?)*)",?RegexOptions.Multiline);
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text +=?"條碼類別:?\n"?+ m.Groups["type"].Value +?"\n";
?????richTextBox2.Text +=?"表示范圍:?\n"?+ m.Groups["range"].Value +?"\n";
}
/*--------輸出--------
條碼類別:
CODE39/CODE93
表示范圍:
A-Z
space,-,.,$,/,+,%
條碼類別:
CODE128A
表示范圍:
A-Z
0-9
space,!,",#,$,%,&,…,(,)*,+,逗號(hào),-,.,/, <,=,>,?,@,[,],^,_
條碼類別:
CODE128B
表示范圍:
A-Z
a-z
0-9
space,!,",#,$,%,&,…,(,)*,+,逗號(hào),-,.,/, <,=,>,?,@,[,],^,_,{,},|,~
條碼類別:
CODE2of5
表示范圍:
0-9
*/

2.2.3   Singleline 單行模式

單行模式改變的是小數(shù)點(diǎn)“.”的匹配行為,使小數(shù)點(diǎn)可以匹配包含換行符“\n”在內(nèi)的任意一個(gè)字符。

這是一個(gè)很不幸的命名,總讓人誤會(huì)它與Multiline多行模式是有關(guān)聯(lián)的,而事實(shí)上它改變的是小數(shù)點(diǎn)的匹配行為,與Multiline多行模式?jīng)]有任何關(guān)聯(lián),由于歷史原因,這一不幸的命名被保留了下來(lái)。使用時(shí)需要注意。

單行模式通常在匹配有換行的文本時(shí)使用,采用小數(shù)點(diǎn)+單行模式的方式匹配任意字符,在.NET中是效率最高的。參考 正則基礎(chǔ)之——小數(shù)點(diǎn)。

典型應(yīng)用:

源字符串:

<a>There is one obvious advantage:</a>
<div>
????<p>
????????You've seen it coming!<br/>
????????Buy now and get nothing for free!<br/>
????????Well, at least no free beer. Perhaps a bear,<br/>
????????if you can afford it.
????</p>
</div>
<a>Now that you've got...</a>
<div>
????<p>
????????your bear, you have to admit it!<br/>
????????No, we aren't selling bears.
????</p>
</div>

需求:取<div>標(biāo)簽之間的內(nèi)容

代碼實(shí)現(xiàn):

MatchCollection?mc =?Regex.Matches(yourStr,?@"<div[^>]*>(?:(?!</div\b).)*</div>",?RegexOptions.Singleline|RegexOptions.IgnoreCase);
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text += m.Value +?"\n-------------------\n";
}
/*--------輸出--------
<div>
????<p>
????????You've seen it coming!<br/>
????????Buy now and get nothing for free!<br/>
????????Well, at least no free beer. Perhaps a bear,<br/>
????????if you can afford it.
????</p>
</div>
-------------------
<div>
????<p>
????????your bear, you have to admit it!<br/>
????????No, we aren't selling bears.
????</p>
</div>
-------------------
*/

2.2.4 Compiled 編譯模式

Compiled改變的是.NET中正則表達(dá)式的編譯方式。啟用了Compiled模式,會(huì)延長(zhǎng)啟動(dòng)時(shí)間,占用更多的內(nèi)存,會(huì)提高匹配速度。當(dāng)然,對(duì)最終性能的影響,需要根據(jù)具體問(wèn)題綜合考慮的。這一模式也是被“濫”用最多的模式之一。

程序運(yùn)行過(guò)程中,第一次遇到正則表達(dá)式,需要加載正則引擎,對(duì)正則表達(dá)式進(jìn)行必要的語(yǔ)法檢查,并做適當(dāng)?shù)膬?yōu)化,最后把它轉(zhuǎn)換為適合正則引擎應(yīng)用的形式。這種“解析”過(guò)程,對(duì)于復(fù)雜的正則表達(dá)式,頻繁調(diào)用或是匹配較大的數(shù)據(jù)源時(shí),對(duì)效率的影響較大。

這時(shí)可以在構(gòu)建正則表達(dá)式時(shí)開(kāi)啟Compiled模式。這樣做會(huì)將正則表達(dá)式直接編譯為MSIL代碼,在正則匹配過(guò)程中,可以由JIT優(yōu)化為更快的本地機(jī)器代碼,獲得更高的匹配速度。但這種方式會(huì)降低正則的解析速度,占用更多的內(nèi)存,而且它占用的內(nèi)存在程序運(yùn)行過(guò)程中會(huì)一直占用,無(wú)法釋放。

什么場(chǎng)景下使用Compiled模式,需要根據(jù)實(shí)際情況具體問(wèn)題具體分析,一般來(lái)說(shuō),以下場(chǎng)景不適合使用Compiled模式:

1. 對(duì)匹配效率沒(méi)有要求的場(chǎng)景;

2. 非常簡(jiǎn)單的正則表達(dá)式;

3. 極少調(diào)用的方法中聲明的正則表達(dá)式;

4. 循環(huán)體中聲明的正則表達(dá)式(除了動(dòng)態(tài)生成的正則表達(dá)式,否則不要在循環(huán)體內(nèi)聲明正則表達(dá)式);

5. 靜態(tài)方法中聲明的正則表達(dá)式(靜態(tài)方法每次調(diào)用都需要重新編輯正則表達(dá)式,使用Compiled模式只會(huì)降低效率)。

2.2.5 RightToLeft 從右到左模式

RightToLeft改變的是正則表達(dá)式匹配的順序,從右到左進(jìn)行匹配。目前只有.NET支持這一模式,但它對(duì)這一模式的支持并不是很完善,有時(shí)容易讓人費(fèi)解,所以除非對(duì)源字符串的構(gòu)成很了解,而且又不得不使用的情況,否則不要輕易使用這一模式。

典型應(yīng)用(參考 求一個(gè)好的算法):

一個(gè)由字母組成的字符串,最長(zhǎng)14位,要求每隔2位加一個(gè)逗號(hào),最左邊不加,求一個(gè)好的算法

例:“abcdefg”    返回“a,bc,de,fg”

代碼實(shí)現(xiàn):

string?test =?"abcdefg";
string?result =?Regex.Replace(yourStr,?@"(?<!^)[a-zA-Z]{2}",?",$0",?RegexOptions.RightToLeft);

2.2.6 None

這一模式指定不開(kāi)啟任何模式。在.NET中RegexOptions 枚舉值是按位“或”組合,None模式我目前只找到一種應(yīng)用場(chǎng)景,就是在動(dòng)態(tài)生成正則表達(dá)式時(shí),動(dòng)態(tài)指定模式時(shí)使用。

///?<summary>
///?動(dòng)態(tài)生成正則參數(shù)列表
///?</summary>
///?<returns></returns>
private?RegexOptions?getParameter()
{
????RegexOptions?roList =?RegexOptions.None;
????if?(cbIgnoreCase.Checked)
????{
?????????roList = roList |?RegexOptions.IgnoreCase;
?????}
?????if?(cbSingleline.Checked)
?????{
??????????roList = roList |?RegexOptions.Singleline;
?????}
?????if?(cbMultiline.Checked)
?????{
??????????roList = roList |?RegexOptions.Multiline;
?????}
?????if?(cbCompiled.Checked)
?????{
??????????roList = roList |?RegexOptions.Compiled;
?????}
?????if?(cbRightToLelft.Checked)
?????{
??????????roList = roList |?RegexOptions.RightToLeft;
?????}
?????return?roList;
}

2.2.7 ExplicitCapture

這一模式改變的是普通捕獲組的匹配行為。將普通捕獲組解釋為非捕獲組,只有顯式命名的命名捕獲組才當(dāng)作捕獲組使用。

捕獲組的作用是將括號(hào)()內(nèi)子表達(dá)式匹配到的內(nèi)容保存到內(nèi)存中一個(gè)組里,供以后引用,在.NET中捕獲組有兩種形式

(Expression) 普通捕獲組

(?<name>Expression) 命名捕獲組

其它形式的(?...)都不是捕獲組。

但是(Expression)這種捕獲組語(yǔ)法規(guī)則也帶來(lái)一個(gè)副作用,在一些不得不使用()的場(chǎng)合,會(huì)默認(rèn)為使用了捕獲組,將匹配到的內(nèi)容保存到內(nèi)存中,而有些情況下這些內(nèi)容并不需要關(guān)心的,浪費(fèi)了系統(tǒng)資源,降低了匹配效率,所以才有了非捕獲組(?:Expression)的出現(xiàn),來(lái)抵消這一副作用。而非捕獲組帶來(lái)的另一個(gè)副作用的就是可讀性的降低。

ExplicitCapture模式是為了在不犧牲匹配效率的前提下,提高正則表達(dá)式的可讀性,一般在命名捕獲組和普通捕獲組混合出現(xiàn),而又不關(guān)心普通捕獲組的正則表達(dá)式中使用,如取鏈接和文字的正則表達(dá)式中

MatchCollection?mc =?Regex.Matches(yourStr,?@"(?is)<a((?!href=).)*href=(?<s>['""]?)(?<url>[^""'\s>]*)\k<s>[^>]*>(?<text>((?!</a>).)*)</a>",?RegexOptions.ExplicitCapture);
foreach?(Match?m?in?mc)
{
??????richTextBox2.Text += m.Groups["url"].Value +?"\n";
?????richTextBox2.Text += m.Groups["text"].Value +?"\n";
}

開(kāi)啟ExplicitCapture模式對(duì)正則表達(dá)式解釋行為的影響,可以參考如下舉例,匹配時(shí)間的正則表達(dá)式

未開(kāi)啟ExplicitCapture模式

string?test =?"<li title=\"截至2009-07-28 20:45:49,用戶的總技術(shù)分為:5988;截至2009-07-26日,用戶的總技術(shù)分排名為:4133\">(...)</li>";
Regex?reg =?new?Regex(@"([01][0-9]|2[0-3])(:[0-5][0-9]){2}");
MatchCollection?mc = reg.Matches(test);
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text += m.Value +?"\n";
?????richTextBox2.Text += m.Groups[1].Value +?"\n";
?????richTextBox2.Text += m.Groups[2].Value +?"\n";
}
/*--------輸出--------
20:45:49
20
:49
*/

開(kāi)啟ExplicitCapture模式

string?test =?"<li title=\"截至2009-07-28 20:45:49,用戶的總技術(shù)分為:5988;截至2009-07-26日,用戶的總技術(shù)分排名為:4133\">(...)</li>";
Regex?reg =?new?Regex(@"([01][0-9]|2[0-3])(:[0-5][0-9]){2}");
MatchCollection?mc = reg.Matches(test);
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text += m.Value +?"\n";
?????richTextBox2.Text += m.Groups[1].Value +?"\n";
?????richTextBox2.Text += m.Groups[2].Value +?"\n";
}
/*--------輸出--------
20:45:49
*/

一般來(lái)說(shuō),關(guān)心的只是整個(gè)正則表達(dá)式匹配的整體,啟用了ExplicitCapture模式后,“([01][0-9]|2[0-3])”和“(:[0-5][0-9])”將不會(huì)被解釋為捕獲組,匹配到的內(nèi)容也不會(huì)保存到內(nèi)存中。

開(kāi)啟ExplicitCapture模式雖然可以提高正則表達(dá)式的可讀性,但ExplicitCapture這一模式本身容易被人忽略,所以這種模式應(yīng)用得也比較少。

一旦使用了ExplicitCapture模式,要注意的是,除非你清楚捕獲組的編號(hào)規(guī)則,否則盡量不要再使用\number方式進(jìn)行反向引用,可以使用\k<name>方式進(jìn)行反向引用。

Regex?reg =?new?Regex(@"href=(['""]?)(?<url>[^'""\s>]+)\1",?RegexOptions.ExplicitCapture);
MatchCollection?mc = reg.Matches(yourStr);
foreach?(Match?m?in?mc)
{
?????richTextBox2.Text += m.Value +?"\n";
}

以上匹配鏈接的代碼通常是得不到任何結(jié)果的,因?yàn)檫@里“\1”引用的內(nèi)容,不再是“(['""]?)”匹配到的內(nèi)容,而是“(?<url>[^'""\s>]+)”匹配到的內(nèi)容,等價(jià)于“(?<url>[^'""\s>]+)\k<url>”,而這樣的字符串,通常是不存在的。

2.2.8 IgnorePatternWhitespace

這一模式忽略正則表達(dá)式中的非轉(zhuǎn)義空白字符,并啟用“#”后面的注釋,通常用于增強(qiáng)正則表達(dá)式的可讀性或是用于教學(xué)目的。

舉個(gè)例子基本上就會(huì)明白了

string?test =?"(One) and ( Two (Three) Four).";
Regex?reg =?new?Regex(@"\(??????????????????????????#普通開(kāi)括弧
??????????????????????????(?>???????????????????????#固化分組
?????????????????????????????\(???(?<OPEN>)?????????#遇到開(kāi)括弧'OPEN'計(jì)數(shù)加1
????????????????????????????|???????????????????????#分支結(jié)構(gòu)
?????????????????????????????\)???(?<-OPEN>)????????#遇到閉括弧'OPEN'計(jì)數(shù)減1
????????????????????????????|???????????????????????#分支結(jié)構(gòu)
?????????????????????????????[^()]+?????????????????#非括弧的其它任意字符
??????????????????????????)*????????????????????????#以上子串出現(xiàn)0次或任意多次
??????????????????????????(?(OPEN)(?!))?????????????#判斷是否還有'OPEN',有則說(shuō)明不配對(duì),什么都不匹配
????????????????????????\)??????????????????????????#普通閉括弧
???????????????????????",?RegexOptions.IgnorePatternWhitespace);
MatchCollection?mc = reg.Matches(test);
foreach?(Match?m?in?mc)
{
??????richTextBox2.Text += m.Value +?"\n";
}

其中的空白字符被忽略,“#”及該行后面的內(nèi)容被解釋為注釋。

2.2.9 ECMAScript

這一模式將按ECMA的JavaScript語(yǔ)義來(lái)解析正則表達(dá)式。通常影響的是以下元字符的匹配行為

\w、\W、\d、\D、\s、\S

使得以上元字符只能匹配ASCII碼字符,而不再是匹配相應(yīng)的Unicode字符。

事實(shí)上比如需求中明確要求只匹配英文字母,數(shù)字,下劃線,而不包含漢字等字符,那么完全可以用“[A-Za-z0-9_]”,而不使用“\w”,雖然不夠簡(jiǎn)潔,但可讀性更好,語(yǔ)義更明確。

這一模式在.NET中的應(yīng)用比較少,如不清楚什么場(chǎng)景下應(yīng)該使用,可以忽略這一模式。

2.2.10 CultureInvariant

這一模式指定忽略語(yǔ)言中的區(qū)域性差異。一般與IgnoreCase模式一起使用,這一模式的應(yīng)用場(chǎng)景很少,一般可以忽略,無(wú)需了解。

2.3 內(nèi)聯(lián)匹配模式

內(nèi)聯(lián)匹配模式在正則表達(dá)式內(nèi)部使用,可以改變局部子表達(dá)式的匹配行為,內(nèi)聯(lián)匹配模式支持的模式較少,僅有immsx五種,但使用起來(lái)更簡(jiǎn)潔,更靈活。在.NET中支持(?imnsx-imnsx:)和(?imnsx-imnsx)兩種形式。

各內(nèi)聯(lián)匹配模式對(duì)應(yīng)的全局匹配模式見(jiàn)匹配模式列表。以下僅就(?i)忽略大小寫模式進(jìn)行講解,其它模式類同。

2.3.1  (?imnsx-imnsx:)形式

語(yǔ)法:(?i:Expression)

這種語(yǔ)法規(guī)則表達(dá)為括號(hào)內(nèi)的子表達(dá)式開(kāi)啟忽略大小寫模式。

舉例:^[A-Z](?i:[A-Z]{9,19})$

以上正則表示,首字符必須為大寫字母,后面跟9到19個(gè)大小寫字母。

string[] test =?new?string[] {?"Abc",?"AbcdefGHIjklmn",?"abcdefghijklmn"?};
Regex?reg =?new?Regex(@"^[A-Z](?i:[A-Z]{9,19})$");
foreach?(string?s?in?test)
{
?????richTextBox2.Text +=?"源字符串:?"?+ s.PadRight(15,?' ') +?"??匹配結(jié)果:?"?+ reg.IsMatch(s) +?"\n";
}
/*--------輸出--------
源字符串:?Abc??????????????匹配結(jié)果:?False
源字符串:?AbcdefGHIjklmn???匹配結(jié)果:?True
源字符串:?abcdefghijklmn???匹配結(jié)果:?False
*/

語(yǔ)法:(?-i:Expression)

這種語(yǔ)法規(guī)則表達(dá)為括號(hào)內(nèi)的子表達(dá)式關(guān)閉忽略大小寫模式。通常與全局匹配模式配合使用,表示全局為忽略大小寫的,局部為嚴(yán)格區(qū)分大小寫。

舉例:<div id="(?-i:TEST)" [^>]*>[\w\s]+</div>

以上正則表示,div標(biāo)簽中,僅匹配id為全大寫的“TEST”的標(biāo)簽內(nèi)容,其余標(biāo)簽不匹配。

string?test =?"<DIV id=\"Test\" class=\"create\">first</div> and <DIV id=\"TEST\" class=\"delete\">second</div>";
Regex?reg =?new?Regex(@"<div id=""(?-i:TEST)""[^>]*>[\w\s]+</div>",?RegexOptions.IgnoreCase);
MatchCollection?mc = reg.Matches(test);
foreach(Match?m?in?mc)
{
??????richTextBox2.Text += m.Value +?"\n";
}
/*--------輸出--------
<DIV id="TEST" class="delete">second</div>
*/

2.3.2  (?imnsx-imnsx)

語(yǔ)法:(?i) 或 (?-i)

(?i)為所在位置右側(cè)的子表達(dá)式開(kāi)啟忽略大小寫模式,直到出現(xiàn)(?-i)或者到表達(dá)式結(jié)束為止;(?-i)為所在位置右側(cè)的子表達(dá)式關(guān)閉忽略大小寫模式,直到出現(xiàn)(?i)或者到表達(dá)式結(jié)束為止。

通常在正則表達(dá)式開(kāi)始位置使用(?i)來(lái)代替RegexOptions.IgnoreCase,使代碼更簡(jiǎn)潔。如提取鏈接和文字的正則表達(dá)式

MatchCollection?mc =?Regex.Matches(yourStr,?@"(?is)<a(?:(?!href=).)*href=(['""]?)(?<url>[^""'\s>]*)\1[^>]*>(?<text>(?:(?!</a>).)*)</a>");
foreach?(Match?m?in?mc)
{
??????richTextBox2.Text += m.Groups["url"].Value +?"\n";
??????richTextBox2.Text += m.Groups["text"].Value +?"\n";
}

3、小結(jié)

.NET中的正則匹配模式基本上已講解完了,最后再來(lái)總結(jié)一下各匹配模式的應(yīng)用場(chǎng)景吧。

RegexOption 成員

內(nèi)聯(lián)字符

作用/應(yīng)用場(chǎng)景

None

N/A

指定不設(shè)置任何選項(xiàng)。

一般在動(dòng)態(tài)指定匹配模式時(shí)使用。

IgnoreCase

i

指定不區(qū)分大小寫的匹配。

只有在正則表達(dá)式中,注意是正則表達(dá)式中,而不是待匹配的源字符串中,涉及到大小寫形式的元字符或是字符序列時(shí),才使用IgnoreCase模式。

Multiline

m

指定多行模式。更改 ^ 和 $ 的含義,以使它們分別與任何行的開(kāi)頭和結(jié)尾匹配,而不只是與整個(gè)字符串的開(kāi)頭和結(jié)尾匹配。

只有在正則表達(dá)式中涉及到多行的“^”和“$”的匹配時(shí),才使用Multiline模式。

ExplicitCapture

n

指定唯一有效的捕獲是顯式命名或編號(hào)的 (?<name>…) 形式的組。這允許圓括號(hào)充當(dāng)非捕獲組,從而避免了由 (?:…) 導(dǎo)致的語(yǔ)法上的笨拙。

ExplicitCapture模式是為了在不犧牲匹配效率的前提下,提高正則表達(dá)式的可讀性,一般在命名捕獲組和普通捕獲組混合出現(xiàn),而又不關(guān)心普通捕獲組的正則表達(dá)式中使用。

Compiled

N/A

指定正則表達(dá)式將被編譯為程序集。生成該正則表達(dá)式的 Microsoft 中間語(yǔ)言 (MSIL) 代碼;以較長(zhǎng)的啟動(dòng)時(shí)間為代價(jià),得到更快的執(zhí)行速度。

以下場(chǎng)景不適合使用:

1.    對(duì)匹配效率沒(méi)有要求的場(chǎng)景;

2.    非常簡(jiǎn)單的正則表達(dá)式;

3.    極少調(diào)用的方法中聲明的正則表達(dá)式;

4.    循環(huán)體中聲明的正則表達(dá)式(除了動(dòng)態(tài)生成的正則表達(dá)式,否則不要在循環(huán)體內(nèi)聲明正則表達(dá)式);

5.    靜態(tài)方法中聲明的正則表達(dá)式(靜態(tài)方法每次調(diào)用都需要重新編輯正則表達(dá)式,使用Compiled模式只會(huì)降低效率)。

Singleline

s

指定單行模式。更改句點(diǎn)字符 (.) 的含義,以使它與每個(gè)字符(而不是除 \n 之外的所有字符)匹配。

單行模式通常在匹配有換行的文本時(shí)使用,采用小數(shù)點(diǎn)+單行模式的方式匹配任意字符,在.NET中是效率最高的。

IgnorePatternWhitespace

x

指定從模式中排除非轉(zhuǎn)義空白并啟用數(shù)字符號(hào) (#) 后面的注釋。請(qǐng)注意,空白永遠(yuǎn)不會(huì)從字符類中消除。

為了提高可讀性,或是為正則表達(dá)式加注釋時(shí)使用。

RightToLeft

N/A

指定搜索是從右向左而不是從左向右進(jìn)行的。具有此選項(xiàng)的正則表達(dá)式將移動(dòng)到起始位置的左邊而不是右邊。

除非對(duì)源字符串的構(gòu)成很了解,而且又不得不使用的情況,否則不要輕易使用這一模式。

ECMAScript

N/A

指定已為表達(dá)式啟用了符合 ECMAScript 的行為。此選項(xiàng)僅可與 IgnoreCase 和 Multiline 標(biāo)志一起使用。將 ECMAScript 同任何其他標(biāo)志一起使用將導(dǎo)致異常。

除非對(duì)這一模式應(yīng)用場(chǎng)景很了解,否則不要使用。

CultureInvariant

N/A

指定忽略語(yǔ)言中的區(qū)域性差異。

很少使用,一般無(wú)需了解。

到此這篇關(guān)于.NET正則基礎(chǔ)之.NET正則匹配模式的文章就介紹到這了,更多相關(guān).NET正則匹配模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論