正则表达式入门及备忘
概述
正則表達(dá)式,主要是用符號(hào)描述了一類(lèi)特定的文本(模式)。而正則表達(dá)式引擎則負(fù)責(zé)在給定的字符串中,查找到這一特定的文本。
本文主要是列出常用的正則表達(dá)式符號(hào),加以歸類(lèi)說(shuō)明。本文僅僅是快速理解了正則表達(dá)式相關(guān)元字符,作一個(gè)備忘,供以后理解更復(fù)雜表達(dá)式的參考,以后關(guān)于正則表達(dá)式的相關(guān)內(nèi)容會(huì)持續(xù)更新本文。示例語(yǔ)言用C#
概述
普通字符
字符集合
速記的字符集合
指定重復(fù)次數(shù)的字符
匹配位置字符
分支替換字符
匹配特殊字符
組,反向引用,非捕獲組
貪婪與非貪婪
回溯與非回溯
正向預(yù)搜索、反向預(yù)搜索
最后
1 普通字符
?最簡(jiǎn)單的一種文本描述,就是直接給出要匹配內(nèi)容。 如要在”Generic specialization, the decorator pattern, chains of responsibilities, and extensible software.” 找到pattern,那么正則式就直接是”heels”即可
string input = "Generic specialization, the decorator pattern, chains of responsibilities, and extensible software.";Regex reg = new Regex("pattern", RegexOptions.IgnoreCase);Console.WriteLine(reg.Matches(input).Count); //output 1 View Code?
2 字符集合
?將字符放在中括號(hào)中,即為字符集合。通過(guò)字符集合告訴正則式引擎從字符集合中的字符,僅匹配出一個(gè)字符。
| 字符 | 匹配的字符 | 示例 |
| [...] | 匹配括號(hào)中的任一字符 | [abc]可以匹配單個(gè)字符a,b或c,但不能匹配其它字符 |
| [^...] | 匹配非括號(hào)中的任一字符 | [^abc]可以匹配任一個(gè)除a,b,c的一個(gè)字符,如d,e,f |
比如單詞灰色gray(英)和grey(美),在一段文本中匹配出gray或grey,那么通過(guò)正則式gr[ae]y 就可以了;又比如要在一段文本中找到me和my,正則式是m[ey]
我們還可以在字符集合中使用連字號(hào) – 來(lái)表示一個(gè)范圍,比如 [0-9] 表示匹配一個(gè)0到9數(shù)字;[a-zA-Z] 表示匹配英文字母;[0-9 a-zA-Z]表示匹配一個(gè)0到9的數(shù)字或英文字母
string input = "The color of shirt is gray and color of shoes is grey too.";Regex reg = new Regex("gr[ae]y", RegexOptions.IgnoreCase);Console.WriteLine(reg.Matches(input).Count); //output 2var matchs = reg.Matches(input);foreach (Match match in matchs){Console.WriteLine(match.Value);//output gray grey} View Code?
3 速記的字符集合
我們常常要匹配一個(gè)數(shù)字,一個(gè)字母,一個(gè)空白符,雖然可以用普通的字符類(lèi)來(lái)表示,但不夠方便,所以正則式提示了一些常用的字符集合的速記符
| 字符 | 匹配的字符 | 示例 |
| \d | 從0到9的任何一個(gè)數(shù)字 | \d\d 可以匹配72,但不能匹配me或7a |
| \D | 非數(shù)字符 | \D\D 可以匹配me,但不能匹配7a或72 |
| \w | 任一個(gè)單詞字符,如A-Z, a-z, 0-9和下劃線(xiàn)字符 | \w\w\w\w可以匹配aB_2,但不能匹配ab_@ |
| \W | 非單詞字符 | \W 可以匹配@,但不能匹配a |
| \s | 任一空白字符,包括了制表符,換行符,回車(chē)符,換頁(yè)符和垂直制表符 | 匹配所有傳統(tǒng)的空白字符 |
| \S | 任一非空白字符 | \S 可以匹配任一非空白字符,如~!@#& |
| . | 任一字符 | 匹配任一字符,換行符除外 |
?
4 指定重復(fù)次數(shù)的字符
指定重復(fù)匹配前面的字符多少次:匹配重復(fù)的次數(shù),不匹配內(nèi)容。比如說(shuō),要在一系列電話(huà)號(hào)碼中找到以158開(kāi)始的11位手機(jī)號(hào),如果我們沒(méi)有學(xué)過(guò)下面的內(nèi)容,正則表達(dá)式為158\d\d\d\d\d\d\d\d;但如果我們學(xué)習(xí)了下面的知識(shí),則正則表達(dá)式為158\d{8}
| 字符 | 匹配的字符 | 示例 |
| {n} | 匹配前面字符n次 | x{2},可以匹配xx,但不能匹配xxx |
| {n,} | 匹配前面字符n次或更多 | x{2,}可以2個(gè)或更多的x,比如可以匹配xx,xxx,xxxx,xxxxxx |
| {n,m} | 匹配前面字符最少n次,最多m次。如果n為0,則可以不指定 | x{2,4},匹配了xx,xxx,xxxx,但不能匹配x,xxxxx |
| ? | 匹配前面的字符0次或1次,相當(dāng)于{0,1} | x? 匹配x或空 |
| + | 匹配前面的字符1次或多次, 相當(dāng)于{1,} | x+ 匹配x,xx,或xxx |
| * | 匹配前面的字符0次或多次 | x* 匹配0個(gè)或多個(gè)x |
?
5 匹配位置的字符
現(xiàn)在我們已經(jīng)學(xué)會(huì)了使用字符集合,字符集合的速記符來(lái)匹配大部分的文本了。但是如果我們遇到以下的情況,怎么辦?
要求匹配文本的第一個(gè)單詞為google
要求匹配文本以bye結(jié)束
要求匹配文本每一行的第一個(gè)單詞為數(shù)字
要求匹配一個(gè)單詞以hel開(kāi)頭
上面的這種匹配一個(gè)位置,但不匹配任何內(nèi)容的需求很正常。在正則表達(dá)式中也提供了一些特殊的字符來(lái)匹配位置(不匹配內(nèi)容)。如用^匹配文本的開(kāi)始位置, 用$匹配文本的結(jié)束位置,\b匹配一個(gè)單詞的邊界
| 字符 | 匹配的字符 | 示例 |
| ^ | 其后的模式必須在字符串的開(kāi)始處,如果是一個(gè)多行字符串,應(yīng)位于任一行的開(kāi)始。對(duì)于多行文本(有回車(chē)符),需要設(shè)置Multiline標(biāo)識(shí) | |
| $ | 前面的模式必須在字符串的結(jié)尾處,如果是一個(gè)多行字符串,應(yīng)該在任一行的末尾 | |
| \b | 匹配一個(gè)單詞的邊界, | |
| \B | 匹配一個(gè)非單詞的邊界,并不在一個(gè)單詞的開(kāi)始或結(jié)尾處 | |
| \A | 前面的模式必須在字符串的開(kāi)始,并忽略多行標(biāo)識(shí) | |
| \z | 前面的模式必須在字符串的末尾,并忽略多行標(biāo)識(shí) | |
| \Z | 前面的模式必須在字符串的末尾,或是位于換行符前 |
?
6 分支替換字符
在字符集合中,我們可以在用中括號(hào)來(lái)指定匹配中括號(hào)中的任一字符,即模式中可以列出多種字符情景,被匹配的文本只要有符合其中的任一情景就可以被匹配出來(lái)。 那有沒(méi)有這樣的一種機(jī)制,同一個(gè)正則式中有多個(gè)模式,只有滿(mǎn)足其中的任一模式就可以被匹配出來(lái)。再配合分組,就可以把一個(gè)復(fù)雜的正則式分成多個(gè)相對(duì)簡(jiǎn)單子的正則式來(lái)做。類(lèi)似于邏輯符號(hào)OR的意思吧。
| 字符 | 匹配的字符 | 示例 |
| | | 選擇匹配符,匹配前面或后面的任一模式 | cat|mouse 可以匹配出cat 或mouse |
7 匹配特殊字符
到現(xiàn)在,我們已經(jīng)知道了字符集合,一些速記的字符集合,匹配位置的字符,指定匹配次數(shù)的字符,分支匹配。我們用的這些符號(hào),在正則表達(dá)式中代表了各種特定的意義。那當(dāng)我們要匹配這些字符本身,我們應(yīng)該怎么辦?在特殊字符前加上\, 以下是一些常用特殊字符的轉(zhuǎn)義字符的列表
| 字符 | 匹配的字符 | 示例 |
| \\ | 匹配字符\ | |
| \. | 匹配字符. | |
| \* | 匹配字符* | |
| \+ | 匹配字符+ | |
| \? | 匹配字符? | |
| \| | 匹配字符| | |
| \( | 匹配字符( | |
| \) | 匹配字符) | |
| \{ | 匹配字符{ | |
| \} | 匹配字符} | |
| \^ | 匹配字符^ | |
| \$ | 匹配字符$ | |
| \n | 匹配換行符 | |
| \r | 匹配回車(chē)符 | |
| \t | 匹配tab鍵 | |
| \f | 匹配垂直制表符 | |
| \nnn | 匹配一個(gè)三位八進(jìn)制數(shù)指定的ASCII字符,如\103匹配一個(gè)大寫(xiě)的C | |
| \xnn | 匹配一個(gè)二位十六進(jìn)制數(shù)指定的ASCII字符,如\x43匹配C | |
| \xnnnn | 匹配一個(gè)四位十六進(jìn)制數(shù)指定的unicode字符 | |
| \cV | 匹配一個(gè)控制字符,如,\cV匹配Ctrl+V |
8 組,反向引用,非捕獲組
組,可以用圓括號(hào),將正則表達(dá)式的部分括起來(lái)并獨(dú)立使用,在圓括號(hào)之間的正則式叫做一個(gè)組。可以將匹配次數(shù)的字符和分支匹配字符應(yīng)用到組。
1 示例: public void Set, public void SetValue
正則式Set(Value)? , 其中(Value)是一個(gè)組,匹配次數(shù)的字符?將應(yīng)用于整個(gè)組(Value),可以匹配到Set或SetValue
2 示例:Out of sight, out of mind
正則式: “(out of) sight, \1 mind”
正則表達(dá)式引擎會(huì)將 “()”中匹配到的內(nèi)容存儲(chǔ)起來(lái),作為一個(gè)“組”,并且可以通過(guò)索引的方式進(jìn)行引用。表達(dá)式中的“\1”,用于反向引用表達(dá)式中出現(xiàn)的第一個(gè)組。 同時(shí)在c#中,也可以通過(guò)組來(lái)訪(fǎng)問(wèn)捕獲到的組的內(nèi)容。注意,Groups[0]是整個(gè)匹配的字符串,組的內(nèi)容從索引1開(kāi)始
?
3 可根據(jù)組名進(jìn)行索引。使用以下格式為標(biāo)識(shí)一個(gè)組的名稱(chēng)(?<groupname>…)
正則式: “(?<Group1>out of) sight, \1 mind”
string input2 = "out of sight, out of mind";Regex reg2 = new Regex(@"(?<Group1>out of) sight, \1 mind");if (reg2.IsMatch(input2)){Console.WriteLine(reg2.Match(input2).Value);//output out of sight, out of mind }Console.WriteLine(reg2.Match(input2).Groups["Group1"].Value); // output out of View Code?
4在表達(dá)式外引用,對(duì)于索外用$索引,或組名用${組名}
示例:Out of of sight, out of mind
正則式 “(?<Group1>[a-z]+) \1”
string input3 = "out of sight, out out of mind mind";Regex reg3 = new Regex(@"(?<Group1>[a-z]+) \1");//匹配重復(fù)的單詞if(reg3.IsMatch(input3)){Console.WriteLine(reg3.Replace(input3, "$1"));//output out of sight, out of mindConsole.WriteLine(reg3.Replace(input3, "${Group1}"));//output out of sight, out of mind} View Code?
5非捕獲組,在組前加上?: 因?yàn)橛械慕M表達(dá)的僅僅是一個(gè)選擇替換,當(dāng)我們不想用浪費(fèi)存儲(chǔ)時(shí),以用不捕獲該組
"(?:out of) sight"
string input4 = "out of sight, out of mind";Regex reg4 = new Regex(@"(?:out of) sight");//使用了非捕獲?:后,在表達(dá)式內(nèi)就不能使用\1去引用了if (reg4.IsMatch(input4)){Console.WriteLine(reg4.Match(input4).Groups[1].Value); // output 空} View Code?
| 字符 | 匹配的字符 | 示例 |
| (?<groupname>exp) | 匹配exp,并捕獲文本到名稱(chēng)為name的組里 | |
| (?:exp) | 匹配exp,不捕獲匹配的文本,也不給此分組分配組號(hào) |
9 貪婪與非貪婪
正則表達(dá)式的引擎默認(rèn)是貪婪,只要模式允許,它將匹配盡可能多的字符。通過(guò)在“重復(fù)描述字符(*,+等)”后面添加“?”,可以將匹配模式改成非貪婪。貪婪與非貪婪與指定重復(fù)次數(shù)的字符的內(nèi)容密切相關(guān)。
| 字符 | 匹配的字符 | 示例 |
| ? | 如果是跟在量詞(即指定匹配次數(shù)的字符)后面,那么正則表達(dá)式則采用非貪婪模式 | ? |
示例 out of sight, out of mind
貪婪正則式 :? .* of? 輸出out of sight, out of
非貪婪正則式 :? .*? of 輸出 out of
另外一個(gè)示例
輸入:The title of cnblog is <h1>code changes the world</h1>
目標(biāo):匹配HTML標(biāo)記
正則式1:<.+>?
正則式1的輸出: <h1>code changes the world</h1>
正則式2:<.+?>
正則式2的輸出: <h1> </h1>
string input1 = "out of sight, out of mind";Regex reg1 = new Regex(@".* of");//默認(rèn)貪婪模式,盡可能的匹配更多的文本。在遇到第一個(gè)of時(shí),正則引擎并沒(méi)有停止下來(lái),繼續(xù)執(zhí)行以期望后面還有一個(gè)of,這樣就可以匹配到更多的文本。如果后面沒(méi)有匹配到新的of,剛執(zhí)行回溯if (reg1.IsMatch(input1)){Console.WriteLine(reg1.Match(input1).Value);//output out of sight, out of }string input2 = "out of sight, out of mind";Regex reg2 = new Regex(@".*? of");//在指定重復(fù)次數(shù)的字符后面加上?,正則式則為非貪婪模式。一但遇到第一個(gè)符合條件的文本,就匹配結(jié)束if (reg2.IsMatch(input2)){Console.WriteLine(reg2.Match(input2).Value);//output out of }string input3 = "The title of cnblog is <h1>code changes the world</h1>";Regex reg3 = new Regex(@"<.+>");//貪婪模式:匹配HTML標(biāo)記var matchs3 = reg3.Matches(input3);foreach (Match match in matchs3){Console.WriteLine(match.Value);//output <h1>code changes the world</h1> }string input4 = "The title of cnblog is <h1>code changes the world</h1>";Regex reg4 = new Regex(@"<.+?>");//非貪婪模式:匹配HTML標(biāo)記var matchs4 = reg4.Matches(input4);foreach (Match match in matchs4){Console.WriteLine(match.Value);//output <h1> </h1>} View Code10 回溯與非回溯
使用“(?>…)”方式進(jìn)行非回溯聲明。由于正則表達(dá)式引擎的貪婪特性,導(dǎo)致它在某些情況下,將進(jìn)行回溯以獲得匹配,請(qǐng)看下面的示例:
示例:Live?for?nothing, die?for?something
正則式(默認(rèn)回溯): “.*thing,”?? 輸出Live for nothing,? 。“.*”由于其貪婪特性,將一直匹配到字符串的最后,隨后匹配“thing”,但在匹配“,”時(shí)失敗,此時(shí)引擎將回溯,并在“thing,”處匹配成功
正則式(非回溯):”(?>.*)thing,” 匹配不到任何東西。由于強(qiáng)制非回溯,所以整個(gè)表達(dá)式匹配失敗
string input1 = "Live for nothing, die for something";Regex reg1 = new Regex(@"(.*)thing,");var matchs1 = reg1.Matches(input1);foreach (Match match in matchs1){Console.WriteLine(match.Value);//output }Regex reg2= new Regex(@"(?>.*)thing,");var matchs2 = reg2.Matches(input1);foreach (Match match in matchs2){Console.WriteLine(match.Value);//output } View Code?
?
| 字符 | 匹配的字符 | 示例 |
| (?>...) | 匹配組內(nèi)表達(dá)式時(shí),不回溯 |
11 正向預(yù)搜索、反向預(yù)搜索(look around)
匹配特定的模式,并聲明前面或后面的內(nèi)容。意思跟匹配位置差不多
?
?
| 字符 | 匹配的字符 | 示例 |
| (?=exp) | 左邊的模式后面必須緊跟著exp,聲明本身不作為匹配結(jié)果的一部分 | |
| (?!exp) | 左邊的模式的后面不能緊跟著exp,聲明本身不作為匹配結(jié)果的一部分 | |
| (?<=exp) | 右邊的模式的前面必須是exp,聲明本身不作為匹配結(jié)果的一部分 | |
| (?<!exp) | 右邊的模式的前面不能是exp,聲明本身不作為匹配結(jié)果的一部分 |
最后
參考地址:
正則表達(dá)式30分鐘入門(mén)教程
Regular Expressions Tutorial
NET Framework Regular Expressions
.NET進(jìn)階系列之一:C#正則表達(dá)式整理備忘
總結(jié)
以上是生活随笔為你收集整理的正则表达式入门及备忘的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java实现循环链表
- 下一篇: 基于nginx环境部署nagios