1. 程式人生 > >JavaScript正則表示式入門

JavaScript正則表示式入門

  工作中,正則表示式用的可能不是很多,一般使用的時候網上都有現成的例項,很少缺乏比較全面的理解。本文主要以匹配HTML標籤為例,簡述下正則表示式常用的功能點。匹配HTML片段如下:

let str = `
    <div id="app">
      <div>21</div> 
      <h1>
        <span>hello</span>
        <span>smile</span>
      </h1>
    <button>按鈕</button></div>
`;

  正則匹配本文檢視結果主要用String.match(RegExp)方法,常用的正則匹配方法為:RegExp.test(String),RegExp.exec(String)

  1、正則表示式的宣告

    正則表示式的宣告方式和普通變數的宣告方式類似,一般情況下有兩種,字面量和正則構造方法RegExp。以匹配span標籤為例,匹配單個span標籤的正則如下:

// 字面量方式
let normalPattern = /span/
// 呼叫正則構造方法
let pattern = new RegExp('span')

  2. 修飾符

    上述的正則,在匹配測試文字是,輸出的結果是一個數組,只有一個元素span,如果我想匹配多個呢,這裡就要引入正則修飾符的概念了,常用的就是 i 和 g。

      i的含義是忽略大小寫,比如用/span/只能去匹配span字串,SPAN匹配不了,如果想匹配SPAN,就要加上i修飾符

      g的含義是global,全域性查詢,正則預設只匹配第一個符合條件的值,如果要全域性匹配,就要加上g修飾符。

    具體寫法如下:

// 字面量方式
let normalPattern = /span/ig
// 呼叫正則構造方法
let pattern = new RegExp('span', 'ig')

  3.字元類別

    以上匹配的文字都非常的基礎,假如我想匹配所有的HTML標籤,該怎麼寫呢?HTML標籤很多,沒法一個個全部羅列出來,我們可以使用字元類別,進行快速的匹配。參考列表如下:

   字元類別,在某種程度上來說,可以理解為一個字符集,如上述列表所示,\d是數字0-9的集合,如果我們要匹配一段文字中所有的數字,可以直接宣告如下正則:

let numberPattern = /\d/g

  假如我要匹配所有的HTML標籤呢?在匹配一個文字之前,我們需要先分析下HTML標籤規律,首先,HTML標籤和一般的XML標籤,都是以尖括號<大頭,以尖括號>結尾,其次,中間只能是英文字母或者數字,最後,數字或字母可能出現一次或者多次。寫正則的第一要素是先歸納總結,總結出規律才能去分析正則的寫法。正則表示式本質上也是一種規律的解釋文字。從我們總結的規律中,我們可以按照如下寫法:

let matchTags = /<\w+>/g

  匹配結果如下:

[ '<div>', '<h1>', '<span>', '<span>', '<button>' ]

  \w代表數字或者字母,+代表匹配一次或者多次,g代表全域性匹配。我們在匹配文字的時候,一種規律有時候不可能只用一次,正則表示式提供了豐富的數量詞語法,能夠滿足我們絕大多數要求,下面的章節會有介紹。

  我們看到,我們匹配的HTML標籤只是前面的標籤,並沒有後面的閉合標籤,我們如何匹配閉合標籤呢?閉合標籤比普通的標籤多了一個斜槓/,如果我們單純的寫/,是不可以的,大家可能意識到,正則表示式的字面量寫法是兩個斜槓/包起來的,如果我們直接寫,會有衝突,這時候,我們需要藉助轉義字元反斜槓\進行轉義即可,一些與正則表示式衝突的,都需要用轉義字元進行轉義,比如特殊字元(),[],還有是一些具有特殊意義的集合,\w,\d....

  匹配閉合標籤的正則如下:

let matchCloseTags = /<\/\w+>/g

  匹配結果:

[ '</div>', '</span>', '</span>', '</h1>', '</button>', '</div>' ]

  4.數量詞

    在字元類中,我們用到了數量詞+,代表匹配一次或多次。正則表示式數量詞遠遠不止這些,具體列表如下所示:  

   舉個例子,假如我要匹配HTML片段中的h標籤,我們都知道h標籤的基本規則為只有一個字母和數字,從上述我們可以得出,我們可以用數量詞{n},正則表示式如下:

let matchH = /<h{1}\d{1}>/g

  匹配結果:

[ '<h1>' ]

  在這裡,我們要記住兩個個數量詞,x*?和x+?,這個是最小匹配原則。假如現在我們要匹配第一個span閉合標籤和文字,即<span>hello</span>,如果我們按照正常思路去寫,以<span>開頭,</span>結尾,中間是任意字元,正則表示式實現如下所示:

let matchSpan = /<span>(\S|\s)+<\/span>/g

  匹配結果可能和我們預想的不大一樣,實際上匹配結果只有一個,如下所示:

[ '<span>hello</span>\n        <span>smile</span>' ]

  正則預設的會全文匹配,並不會按照最小匹配原則,即找到符合條件的文字就返回,他會最大程度的去匹配符合條件的文字。如果我們要分別匹配兩段span標籤,我們就需要用到最小匹配原則的數量詞,具體如下:

let matchSpan = /<span>(\S|\s)*?<\/span>/g
let matchSpan2 = /<span>(\S|\s)+?<\/span>/g

  文字匹配結果:

[ '<span>hello</span>', '<span>smile</span>' ]

  5.集合

    正則表示式中,集合使用也比較多,語法比較簡單,所有需要匹配的文字依次放在中括號[]中,比如如果你想匹配abc三個字母,pattern=/[abc]/,如果不想匹配abc,那就是pattern=[^abc],如果匹配數字,那就是/[0-9]/,-代表一個連續的集合,字母就是[a-zA-Z]

  6.邊界

    邊界最簡單的用法,^代表匹配輸入的開始,$代表匹配輸入的結束。

  7.分組

    假如現在有這樣一個需求,需要匹配span標籤裡的文字,而不需要span標籤, 此時可能會用到分組,從字面意思上來說,分組就是把規則分類。分組的語法比較簡單,就是小括號()。轉換為正則的語法如下:

let matchSpanText = /(<span>)(\S+)+?(<\/span>)/
let result = str.match(matchSpanText)

 匹配結果如下圖所示:

  

   從上圖可以看出,匹配結果陣列result長度為4,第一部為匹配的結果,第二部分為(span)匹配的結果,第三部分為(\S+)匹配的結果,第四部分為(</span>)匹配的結果,如果我們要拿純文字,直接去arr[2]即可。我們也能得出一個結論,所謂分組,其實就是普通的正則匹配加上分組條件的匹配集合。

  8.斷言

    斷言是個好東西,能夠解決許多比較棘手的問題,比如上面的例子,我想拿兩個標籤中間的文字,採用分組去取,是可以實現,但是就看每次都要拿匹配結果的第三個陣列,有點不爽,怎麼辦呢,斷言可以幫你解決這個煩惱,匹配的結果直接是文字。斷言的基本規則如下:

  

   從基本規則中,我們可以從字面上得出,斷言可以設定一個文字前後的匹配規則,我們可以將匹配標籤中間的文字規則改造如下:

let matchSpanTextDescribe = /(?<=<span>)(\S+)+?(?=<\/span>)/g
let result = str.match(matchSpanTextDescribe)

  匹配結果如下:

  參考資料:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp#bounda