.NETCoreCSharp 中級篇2-4
本節內容為正規表示式的使用
簡介
有的時候,你是否有過這種需求:判斷一個Ip地址、郵箱、密碼規則是否合法。如果讓你使用if一類的傳統方法進行處理,你肯定會被逼瘋的。而對於絕大多數的程式語言而言,都有一個字串處理利器————正規表示式。它可以輕鬆的讓字串和規則匹配上。有點這樣的意思,從前你是判斷字串,去遍歷它,而有了正規表示式,你是在書寫一個通用性質的規則,讓字串與規則進行匹配。正規表示式本質上就是一串蘊含了一些特殊字元規則的字串,因此我們書寫正規表示式其實是在書寫一個字串,只是它代表了一定的規則而已。
常見的幾種正則符號
事實上正規表示式沒有過多的知識點,只是一些技巧性的訓練,但請相信我,正規表示式是非常重要的。熟練的使用下列的正則符號會對你大有脾益。
元字元
元字元 | 說明 |
---|---|
. | 匹配除了換行符以外的任意字元 |
\w | 匹配字母、數字、下劃線以及漢字 |
\s | 匹配任意空白符 |
\d | 匹配數字 |
\b | 匹配單詞的開始或結束 |
^ | 匹配字串的開始 |
$ | 匹配字串的結束 |
1.例如匹配abc開頭的字串
\babc 或者 ^abc
2.匹配5位數字的字串
^\d\d\d\d\d$
重複限定符號
有了元字元就可以寫不少的正規表示式了,但細心的你們可能會發現:別人寫的正則簡潔明瞭,如果你只使用元字元進行正規表示式的書寫,既不美觀也不實用,因此我們使用重複限定符進行重複資料的處理,下面我們來看一些限定符:
字元 | 說明 |
---|
- | 重複0次或多次
- | 重複一次或一次以上
? | 重複0次或一次
{n} | 重複n次
{n,} | 重複n次或更多次
{n,m} | 重複n到m次
現在我們就能書寫相當美觀的正規表示式了,例如:
1.匹配7位數字的電話號碼
^\d{7}$
2.匹配138開頭的手機號
^138\d{8}
3.匹配a開頭,若干個b結尾的字串
^ab*$
分組
現在我們已經學會以一點關於書寫正規表示式的方法,不過,我們現在無論是匹配還是重複都是針對單個字元進行操作,假如說我希望匹配一個以ab為迴圈的重複字串應該如何去處理呢?
答案很簡單,就是分組,分組我們通常使用()進行分組,例如匹配以ab為迴圈的字串為:
^(ab)*
跳脫字元
有的時候,我們需要匹配的字串中本身就含有正規表示式中的關鍵字元,我們則需要轉義,例如我們需要匹配(ab)為迴圈的字串:
^(\(ab\))*
反斜槓\就是我們的跳脫字元。不過對於C#中,字串含有反斜槓會自動轉義,為了避免這種情況,我們需要在字串之前加上@或者將將跳脫字元轉義,也就是\兩個斜槓
條件或
有的時候,我們需要匹配的字串可能是ab開頭也有可能是cd開頭,這個時候我們就使用條件語句處理,例如:
^(ab|cd)*
用邏輯或“|”進行處理。
區間匹配
有的時候,我們有可能是需要匹配比如說138-150之間所有數字開頭的字串,或者說A-F按字母表順序內的字母開頭,我們可以這樣
^[138-150]*
^[A-F]*
反義
之前我們談論的都是字串中含有什麼什麼,現在我們可能需要匹配到字串中不含有的字元,那麼我們就需要使用反義,如下表
元字元 | 說明 |
---|---|
\W | 匹配不是字母、數字、下劃線以及漢字 |
\S | 匹配不是空白符 |
\D | 匹配不是數字 |
\B | 匹配不是單詞的開始或結束 |
[^x] | 匹配出了x以外的任意字元 |
貪婪模式與懶惰模式
貪婪
貪婪是當正規表示式中包含能接受重複的限定符時,通常的行為是(在使整個表示式能得到匹配的前提下)匹配儘可能多的字元,這匹配方式叫做貪婪匹配。特性:一次性讀入整個字串進行匹配,每當不匹配就捨棄最右邊一個字元,繼續匹配,依次匹配和捨棄(這種匹配-捨棄的方式也叫做回溯),直到匹配成功或者把整個字串捨棄完為止,因此它是一種最大化的資料返回,能多不會少。
事實上我們之前所談論的重複限定符就是一種貪婪量詞
舉個例子例如我們需要匹配由2-5個數字組成的字串,假設有這樣一串數字51354 8454 1 568,使用^\d{2,5}進行匹配的結果是51354 8454 568,事實上對於這些而言,匹配兩個就已經滿足了,例如51已經滿足該正則式,但是在貪婪匹配中,它會盡可能的多匹配,將整個字串輸出。
如果多個貪婪量詞疊加在一起,如果字串能滿足他們各自最大程度的匹配時,就互不干擾,但如果不能滿足時,會根據深度優先原則,也就是從左到右的每一個貪婪量詞,優先最大數量的滿足,剩餘再分配下一個量詞匹配。
懶惰
懶惰匹配:當正規表示式中包含能接受重複的限定符時,通常的行為是(在使整個表示式能得到匹配的前提下)匹配儘可能少的字元,這匹配方式叫做懶惰匹配。特性:從左到右,從字串的最左邊開始匹配,每次試圖不讀入字元匹配,匹配成功,則完成匹配,否則讀入一個字元再匹配,依此迴圈(讀入字元、匹配)直到匹配成功或者把字串的字元匹配完為止。
使用懶惰量詞就是在貪婪量詞後面中加?,對於之前的例子,他會匹配成51 35 84 54 56
擴充
零寬斷言
零寬斷言用於查詢在某些內容(但並不包括這些內容)之前或之後的東西,也就是說它們像\b,^,$那樣用於指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱為零寬斷言。最好還是拿例子來說明吧: 斷言用來宣告一個應該為真的事實。正規表示式中只有當斷言為真時才會繼續進行匹配。
非常抽象而且籠統,對吧,事實上我也那麼覺得,以上內容來自百度百科,因為我實在是很難解釋這個東西,你可以理解為匹配不含正則結果的內容吧。
正向先行斷言(正前瞻)
正前瞻的語法為:
//pattern為正則式
(?=pattern)
它用於匹配pattern表示式之前的內容,並不返回本身。感覺還是很奇怪對吧,舉一個例子:今年我市GDP為5600億元。假設你要將這句話中的5600取出來,你使用正前瞻的方式應該怎麼做?
\d+(?=億元)
正向後行斷言(正後顧):
正後顧的語法為:
//pattern為正則式
(?<=pattern)
與正前瞻相反,他是返回pattern之後的內容,如果繼續實現之前的內容,那麼表示式就會變成
(<=今年我市GDP為)\d+
負向先行斷言(負前瞻)
負前瞻的語法為:
//pattern為正則式
(?!pattern)
匹配非pattern表示式的前面內容,不返回本身。還是舉之前的例子,我要找到5600億元之前的字母,那麼可以是
[A-Z]+(?!5600億元)
負向後行斷言(負後顧)
這個想必我不需要進行講解各位也應當能思考出如何書寫及使用了,他的語法類似的是:
//pattern為正則式
(?<!pattern)
作用當然是匹配非pattern之後的內容。
我在這裡就舉這幾個例子,還有一些很好的使用手冊你可以參考Microsoft Documents。
捕獲與非捕獲
捕獲你可以理解為將表示式按組分配,例如你匹配一個電話010-8511561,010是區號,我們有可能利用正則式將它單獨取出來。
數字編號捕獲組
語法就是我們之前的分組,但是匹配這個電話號碼的時候,他的表示式如果是
((\d{3})-(\d{7}))
那麼他會分為三組,第一組是完整的電話,第二組是我們的區號,第三組是我們的電話號碼。
命名編號捕獲組
語法:
(?<name>exp)
這個name就是你自己自定義的,例如之前的我們可以寫成
(?<quhao>\d{3})-(?<haoma>\d{7})
這樣我們可以透過名稱進行訪問組內資料,具體的使用我會在後面進行講解。
非捕獲組
同之前相反,它用於表示不需要分組的資料
(?:exp)
例如我們不需要區號,那麼正則式就變成了
(?:\d{3})-(\d{7})
反向引用
捕獲會返回一個捕獲組,這個分組是儲存在記憶體中,不僅可以在正規表示式外部透過程式進行引用,也可以在正規表示式內部進行引用,這種引用方式就是反向引用。
同樣的,根據捕獲組命名規則,反向引用也有兩種
1- 數字反向引用:\k或\number
2- 命名反向引用:\k或'name'
反向引用通常和捕獲組是一同使用的,它的作用主要是用來查詢一些重複的內容或者做替換指定字元。比如要查詢一串字母"aabbbbgbddesddfiid"裡成對的字母。
我們捋捋思路:
- 首先我們要有一個匹配字母的捕獲組:(\w)
- 然後(\w)\1
這樣就可以了,\1代表的是1分組,這樣就是一個匹配成對字母的正則式了。
如何使用正規表示式
位於 System.Text.RegularExpressions 空間下的 Regex 可以對正規表示式進行處理。
Match
這是匹配結果的物件,內含這幾個常用的屬性及方法
- Value:匹配值
- Groups:分組
- Index:匹配值的第一個字元的索引
- Success:是否符合正則式
- NextMatch:下一個符合的匹配值
Regex.Matches
匹配多個符合的結果,返回一個MatchCollection陣列,使用foreach並轉換成Match物件進行訪問.
- IsMatch:是否符合正則式
- Replace:替換匹配上正則式的字串
- Split:按匹配上的字串進行分割
- Match:返回第一個符合正則式的字串
- Matches:返回所有符合的字串
Reference
如果我的文章幫助了您,請您在github.NETCoreGuide專案幫我點一個star,在部落格園中點一個關注和推薦。