咨詢電話:023-6276-4481
熱門文章
電 話:023-6276-4481
郵箱:broiling@qq.com
地址:重慶市南岸區(qū)亞太商谷6幢25-2
替換
Regex類有一個靜態(tài)的Replace方法,其實例也有一個Replace方法,這個方法很強大,因為它可以傳入一個delegate,這樣,你可以自定義每次捕獲匹配時,如何處理捕獲的內(nèi)容。
public static void Main()
{
string s = "1 12 3 5";
s = Regex.Replace(s,@"\d+",new MatchEvaluator(CorrectString),RegexOptions.Compiled|RegexOptions.IgnoreCase);
Console.WriteLine(s);
Console.ReadLine();
}
private static string CorrectString(Match match)
{
string matchValue = match.Value;
if(matchValue.Length == 1)
matchValue = "0" + matchValue;
return matchValue;
}
以上這段代碼說明了如果使用delegate MatchEvaluator來處理正則的Match結(jié)果,該代碼返回"01 12 03 05"。Replace方法除了使用delegate來處理捕獲的Match,還可以用字符串來替換Match的結(jié)果,而用字符串來替換Match結(jié)果除了把Match結(jié)果靜態(tài)的替換成一個固定的文本外,還可以使用以下語法來更方便的實現(xiàn)你需要的功能:
$number | 把匹配的第number組替換成替換表達式,還有這句話怎么寫也表達不清楚意思,還是來個例子吧: ![]() ![]() ![]() ![]() ![]() ![]() ![]() 這段代碼返回的是 “01 012 03 05” 就是說,對組一的每個匹配結(jié)果都用"0$1"這個表達式來替換,"0$1"中"$1"由組1匹配的結(jié)果代入 |
${name} | 把匹配的組名為"name"的組替換成表達式, 上例的Regex expression改成@"(?<name>\d+)(?#這個是注釋)"后面的替換式改為"0${name}"結(jié)果是一樣的 |
$$ | 做$的轉(zhuǎn)義符,如上例表達式改成@"(?<name>\d+)(?#這個是注釋)"和"$$${name}",則結(jié)果為"$1 $12 $3 $5" |
$& | 替換整個匹配 |
$` | 替換匹配前的字符 |
$' | 替換匹配后的字符 |
$+ | 替換最后匹配的組 |
$_ | 替換整個字符串 |
后面的選項,大家自己寫個例子體味一下。
*注,上例中的(?#這個是注釋)說明了正則的內(nèi)聯(lián)注釋語法為(?#)
表達項選項
正則表達式選項RegexOptions有如下一下選項,詳細說明請參考聯(lián)機幫助
RegexOptions枚舉值 | 內(nèi)聯(lián)標(biāo)志 | 簡單說明 |
ExplicitCapture | n | 只有定義了命名或編號的組才捕獲 |
IgnoreCase | i | 不區(qū)分大小寫 |
IgnorePatternWhitespace | x | 消除模式中的非轉(zhuǎn)義空白并啟用由 # 標(biāo)記的注釋。 |
MultiLine | m | 多行模式,其原理是修改了^和$的含義 |
SingleLine | s | 單行模式,和MultiLine相對應(yīng) |
這里我提到內(nèi)聯(lián)標(biāo)志,是因為相對于用RegexOptions在new Regex時定義Regex表達式的全局選項來說,內(nèi)聯(lián)標(biāo)志可以更小粒度(以組為單位)的定義匹配選項,從而更方便表達我們的思想
語法是這樣的:(?i:expression)為定義一個選項,(?-i:expression)為刪除一個選項,(?i-s:expression)則定義i,刪除s,是的,我們可以一次定義很多個選項。這樣,通過內(nèi)聯(lián)選項,你就可以在一個Regex中定義一個組為匹分大小寫的,一個組不匹分大小寫的,是不是很方便呢?
組的概念
一個正則表達式匹配結(jié)果可以分成多個部分,這就是組(Group)的目的。能夠靈活的使用組后,你會發(fā)現(xiàn)Regex真是很方便,也很強大。
先舉個例子
public static void Main()
{
string s = "2005-2-21";
Regex reg = new Regex(@"(?<y>\d{4})-(?<m>\d{1,2})-(?<d>\d{1,2})",RegexOptions.Compiled);
Match match = reg.Match(s);
int year = int.Parse(match.Groups["y"].Value);
int month = int.Parse(match.Groups["m"].Value);
int day = int .Parse(match.Groups["d"].Value);
DateTime time = new DateTime(year,month,day);
Console.WriteLine(time);
Console.ReadLine();
}
以上的例子通過組來實現(xiàn)分析一個字符串,并把其轉(zhuǎn)化為一個DateTime實例,當(dāng)然,這個功能用DateTime.Parse方法就能很方便的實現(xiàn)。
在這個例子中,我把一次Match結(jié)果用(?<name>)的方式分成三個組"y","m","d"分別代表年、月、日。
現(xiàn)在我們已經(jīng)有了組的概念了,再來看如何分組,很簡單的,除了上在的辦法,我們可以用一對括號就定義出一個組,比如上例可以改成
public static void Main()
{
string s = "2005-2-21";
Regex reg = new Regex(@"(\d{4})-(\d{1,2})-(\d{1,2})",RegexOptions.Compiled);
Match match = reg.Match(s);
int year = int.Parse(match.Groups[1].Value);
int month = int.Parse(match.Groups[2].Value);
int day = int .Parse(match.Groups[3].Value);
DateTime time = new DateTime(year,month,day);
Console.WriteLine(time);
Console.ReadLine();
}
從上例可以看出,第一個括號對包涵的組被自動編號為1,后面的括號依次編號為2、3……
public static void Main()
{
string s = "2005-2-21";
Regex reg = new Regex(@"(?<2>\d{4})-(?<1>\d{1,2})-(?<3>\d{1,2})",RegexOptions.Compiled);
Match match = reg.Match(s);
int year = int.Parse(match.Groups[2].Value);
int month = int.Parse(match.Groups[1].Value);
int day = int .Parse(match.Groups[3].Value);
DateTime time = new DateTime(year,month,day);
Console.WriteLine(time);
Console.ReadLine();
}
再看上例,我們用(?<數(shù)字>)的方式手工給每個括號對的組編號,(注意我定義1和2的位置時不是從左到右定義的)
通過以上三例,我們知道了給Regex定義Group的三種辦法以及相應(yīng)的引用組匹配結(jié)果的方式。
然后,關(guān)于組定義,還有兩點請注意:
1、因為括號用于定義組了,所以如果要匹配"("和")",請使用"\("和"\)"(關(guān)于所有特殊字符的定義,請查看相關(guān)Regex expression幫助文檔)。
2、如果定義Regex時,使用了ExplicitCapture選項,則第二個例子不會成功,因為此選項要求顯式定義了編號或名字的組才捕獲并保存結(jié)果,如果你沒有定義ExplicitCapture選項,而有時又定義了類式于(A|B)這樣的部分在表達式,而這個(A|B)你又并不想捕獲結(jié)果,那么可以使用“不捕獲的組”語法,即定義成(?:)的方式,針對于(A|B),你可以這樣來定義以達到不捕獲并保存它到Group集合中的目的--(?:A|B)。
反向引用
反向引用,指把匹配出來的組引用到表達式本身其它地方,比如,在匹配HTML的標(biāo)記時,我們匹配出一個<a>,我們要把匹配出來的a引用出來,用來找到</a>,這個時候就要用到反向引用。
語法
a、反向引用編號的組,語法為\number
b、反向引用命名的組,語法為\k<name>
舉例
a、匹配成對的HTML標(biāo)簽
@"<(?<tag>[^\s>]+)[^>]*>.*</\k<tag>>"
b、匹配兩個兩個重疊出現(xiàn)的字符
public static void Main()
{
string s = "aabbc11asd";
Regex reg = new Regex(@"(\w)\1");
MatchCollection matches = reg.Matches(s);
foreach(Match m in matches)
Console.WriteLine(m.Value);
Console.ReadLine();
}
返回結(jié)果為aa bb 11
輔助匹配組
以下幾種組結(jié)構(gòu),括號中的Pattern都不作為匹配結(jié)果的一部分進行保存
1、正聲明(?=)
涵義:括號中的模式必須出現(xiàn)在聲明右側(cè),但不作為匹配的一部分
public static void Main()
{
string s = "C#.net,VB.net,PHP,Java,JScript.net";
Regex reg = new Regex(@"[\w\#]+(?=\.net)",RegexOptions.Compiled);
MatchCollection mc = reg.Matches(s);
foreach(Match m in mc)