正則表達式初探

本章主要想和你們分享下正則表達式的一些基礎用法,但願可以對一些小白有所幫助,也爲了防止本身之後遺忘相關知識點,下面咱們正式進入主題。正則表達式

1、正則表達式

  一、正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱爲元字符)組成的文字模式。
  二、正則表達式做爲一個模板,將某個字符模式與所搜索的字符串進行匹配。
  三、在編寫處理字符串的程序或網頁時,常常會有查找或替換符合某些複雜規則的字符串的須要。
  四、正則表達式就是記錄文本規則的代碼。緩存

  做用:
    一、查找數據
    二、替換數據

  正則表達式能作什麼(字符串的匹配、字符串的提取、字符串的替換網絡

2、正則表達式的構成

  一、普通字符(若是直接寫多個普通字符,則會被當作一個總體的字符串來匹配)測試

    這包括全部的大小寫字母字符,全部數字,全部標點符號以及一些特殊符號。
    例如:Hello world xyh666ui

  二、定義字符集(取值範圍(該點都是匹配單個字符,要想匹配字符串須要結合限定符來實現)
    [a-e] 表示a到e這些字符中的某一個字符
    [aeiou] 表示aeiou這5個字符其中的某一個字符
    [a-zA-Z] 表示大寫、小寫字母中的某一個字符
    [0-9] 表示0到9之間某一個數字spa

    表明非
    [^lsjd]  :不是中括號中的任意一個字符
    [^a-f]  :a-f範圍外的任意一個字符code

  三、組合字符(大寫表示非)(該點都是匹配單個字符,要想匹配字符串須要結合限定符來實現)blog

    \d  :匹配一個數字字符。等價於[0-9]。
    \D  :匹配一個非數字字符。等價於[^0-9]。
    \w  :匹配一個字母或一個數字或一個下劃線或一個漢字。
    \W  :匹配一個非字母、非數字、非下劃線和非漢字的字符。
    \s  :匹配一個任意的空白符,包括空格、製表符、換頁符等等。等價於[ \f\n\r\t\v]。
    \S  :匹配任意一個非空白符。等價於[^ \f\n\r\t\v]。
    \b  :匹配單詞的開始或結束的位置。
    \B  :匹配不是單詞開頭或結束的位置。ci

  四、特殊字符字符串

    $  :表示字符串的結尾位置(以什麼結尾)
     :表示字符串的開始位置(以什麼開始)(在取值範圍中還表示非)
     :一個點表示匹配一個除換行符 \n以外的任何單字符(匹配單個字符,要想匹配字符串須要結合限定符來實現)
    或者的意思,指明兩項之間的一個選擇 與[...]相似
     :這個符號是用來轉義
    ( ) 分組,標記一個子表達式的開始和結束位置

  五、經常使用限定符
    =================匹配次數=================
    {m}  :其前一單元嚴格出現m次(重複m次)
    {m,}  :其前一單元出現至少m次(重複m次或更屢次)
    {m,n}  :其前一單元出現至少m次,最多n次(重複m到n次)
    =======================================
    =================屢次匹配=================
      :其前面那個單元出現0次或任意次數(重複零次或更屢次)
      : 其前面那個單元出現1次或1次以上 至少匹配一次(重複一次或更屢次)
    ?  : 其前面那個單元出現0次或1次(重複零次或一次)懶惰匹配(儘量短匹配)
    =======================================
  六、貪婪與懶惰(貪婪模式和非貪婪模式)(儘量長匹配和儘量短匹配)
    *? 重複任意次,但儘量少重複
    +? 重複1次或更屢次,但儘量少重複
    ?? 重複0次或1次,但儘量少重複
    {n,m}? 重複n到m次,但儘量少重複
    {n,}? 重複n次以上,但儘量少重複

  七、分組

    當用()定義了一個正則表達式組後,正則引擎則會把被匹配的組按照順序編號,存入緩存。

    默認狀況下,每一個分組會自動擁有一個組號,規則是:從左向右,以分組的左括號爲標誌,第一個出現的分組的組號爲1,第二個爲2,以此類推。

    咱們能夠經過「\數字」的方式進行引用已經存入緩存的組。\1引用第一個匹配的組,\2引用第二個組,以此類推。

    括號內的內容會被當成一個總體進行匹配。

  八、非獲取匹配和預查(零寬斷言)

    非獲取匹配:是指正則引擎不會把被匹配的組存入緩存,咱們也沒法經過「\數字」的方式進行引用咱們的組。

    預查預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配以後當即開始下一次匹配的搜索,而不是從包含預查的字符以後開始。(即用來預查的表達式字符串不會被消耗,它只是用於指定一個位置

    零寬斷言:用於查找在某些內容(但並不包括這些內容)以前或以後的東西,也就是說它們像\b,^,$那樣用於指定一個位置,這個位置應該知足必定的條件(即斷言),所以它們也被稱爲零寬斷言。

    ===========================================================================================

    (?=exp)也叫零寬度正預測先行斷言,它斷言自身出現的位置的後面能匹配表達式exp。好比\b\w+(?=ing\b),匹配以ing結尾的單詞的前面部分(除了ing之外的部分),如查找I'm singing while you're dancing.時,它會匹配sing和danc。

    (?<=exp)也叫零寬度正回顧後發斷言,它斷言自身出現的位置的前面能匹配表達式exp。好比(?<=\bre)\w+\b會匹配以re開頭的單詞的後半部分(除了re之外的部分),例如在查找reading a book時,它匹配ading。

    ===========================================================================================

    (?:pattern) 非獲取匹配,匹配pattern但不獲取匹配結果,不進行存儲供之後使用。這在使用或字符「(|)」來組合一個模式的各個部分時頗有用。例如「industr(?:y|ies)」就是一個比「industry|industries」更簡略的表達式。

    (?=pattern) 非獲取匹配,正向確定預查,在任何匹配pattern的字符串開始處匹配查找字符串,該匹配不須要獲取供之後使用。例如,「Windows(?=95|98|NT|2000)」能匹配「Windows2000」中的「Windows」,但不能匹配「Windows3.1」中的「Windows」。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配以後當即開始下一次匹配的搜索,而不是從包含預查的字符以後開始。

    (?!pattern) 非獲取匹配,正向否認預,在任何不匹配pattern的字符串開始處匹配查找字符串,該匹配不須要獲取供之後使用。例如「Windows(?!95|98|NT|2000)」能匹配「Windows3.1」中的「Windows」,但不能匹配「Windows2000」中的「Windows」。

    (?<=pattern) 非獲取匹配,反向確定預查,與正向確定預查相似,只是方向相反。例如,「(?<=95|98|NT|2000)Windows」能匹配「2000Windows」中的「Windows」,但不能匹配「3.1Windows」中的「Windows」。

    (?<!patte_n) 非獲取匹配,反向否認預查,與正向否認預查相似,只是方向相反。例如「(?<!95|98|NT|2000)Windows」能匹配「3.1Windows」中的「Windows」,但不能匹配「2000Windows」中的「Windows」。

3、C#代碼調用正則表達式

    命名空間 System.Text.RegularExpressions
    
    1new Regex(正則表達式).IsMatch(要匹配的字符串)   返回bool
    2、Regex.Match
        Match match = Regex.Match("age=30", @"^(.+)=(.+)$");
        if (match.Success)
        {
            Console.WriteLine(match.Groups[0].Value);//第0組 輸出完整的字符串 age=30
            Console.WriteLine(match.Groups[1].Value);//第1組 age
            Console.WriteLine(match.Groups[2].Value);//第2組 30
        }
    3、Regex.Matches
        StringBuilder sb = new StringBuilder();
        sb.Append("<Name>張三</Name>\r\n<Name>李四</Name>\r\n<Name>王五</Name>");

        MatchCollection mc = Regex.Matches(sb.ToString(), @"(?<=<Name>).*(?=</Name>)");
        foreach (Match m in mc)
        {
            Console.WriteLine(m.Value);
        }

4、示例說明

接下來針對第二大點的內容咱們舉些例子來講明:

示例1(普通字符):

咱們用 xyh 來匹配 xyh123 以下圖所示:

 從上面的正則表達式測試器匹配的結果能夠看出:若是直接寫多個普通字符,則會被當作一個總體的字符串來匹配。

 

示例2(元字符和限定符):

咱們用 \d 來匹配 xyh123 以下圖所示:

 從匹配的結果能夠發現\d只是匹配單個數字,因此有三個結果,分別爲一、二、3,那若是想匹配一整個字符串123要怎麼辦呢?此時就要結合限定符來實現了。繼續來看下下面的一張圖。

 從圖中能夠看出結合限定符後就能夠實現匹配到123這個字符串了。

 

示例3(普通字符和元字符組合):

咱們用 https://www\..+\.com 來匹配這麼一句話:https://www.jd.com兩個連接https://www.taobao.com  以下圖所示:

 能夠發現匹配的結果爲完整的一整句話,那爲何不是匹配出2個結果分別爲 https://www.jd.com 和 https://www.taobao.com 呢?

 那是由於默認狀況下正則表達式採用貪婪模式匹配(即儘量多匹配),因此匹配出了完整的一句話,此時能夠用?來實現非貪婪模式匹配(即儘量少匹配),以下圖所示:

 這樣就匹配出了2個結果

 

示例4(分組):

 咱們用 (abc)\1 來匹配 abcabc666 以下圖所示:

 從圖中能夠看出匹配結果爲abcabc,爲何會是這樣呢?首先咱們分組(abc)匹配到存入緩存中的值爲abc,經過\1的方式就取到了存入緩存中的第1個分組值abc,這個分組值abc與原來分組(abc)匹配到的字符串abc組成新的匹配字符串abcabc,用新的匹配字符串abcabc去匹配abcabc666獲得的匹配結果就是abcabc了。

 

示例5(非獲取匹配):

非獲取匹配(?:pattern)以下圖所示:

 從圖中能夠看出非獲取匹配,匹配pattern但不獲取匹配結果,不進行存儲供之後使用。所以沒法經過「\數字」的方式來獲取。

 

示例6(預查和零寬斷言):

預查不消耗字符,它只是用於指定一個位置,以下圖所示:

 從圖中能夠看出用 ab(?=a) 來匹配 ababa123 時會獲得兩個結果而不是一個結果,那是由於預查不消耗字符(即不會消耗用來預查用的表達式exp對應的字符),它只是用於指定一個位置,因此在第3個位置的a(即第2個a)沒有被消耗掉。當匹配到第1個結果ab後會從第3個位置的a(即第2個a)開始查找下一個能匹配的字符串,而不是從第4個位置的b(即第2個b)開始查找,這就解釋了爲何會匹配到2個結果了。

 

PS:本文僅是我的看法 ,若有表述錯誤歡迎評論指正!

正則表達式測試器:

連接:https://pan.baidu.com/s/1CwyrLH2dwbBk1KVi2FCGDw 
提取碼:nwyc
相關文章
相關標籤/搜索