正則表達式語法入門

概述

本文主要經過對正則表達式的語法進行一些簡單的介紹,從而讓沒有接觸過或者想學習正則表達式的同窗有一個基礎的瞭解,從而可以看懂和編寫使用通常的正則表達式。javascript

本文的主要內容爲:java

  • 正則表達式的字符匹配
  • 正則表達式的位置匹配
  • 正則表達式的括號與捕獲組

本文的主要受衆是想要學習正則表達式又不知道從何入手的同窗。若是你已經使用過正則表達式,能夠快速瀏覽本文,強化本身的記憶便可。正則表達式

字符匹配

匹配規則

在正則表達式中,分爲精確匹配和模糊匹配兩種。顧名思義,精確匹配就是匹配特定的字符或者位置;而非精確匹配就是帶有必定的範圍的匹配。具體示例以下:瀏覽器

const reg1 = /ab/; //精確匹配

const reg2 = /ab+/; //模糊匹配

不一樣的匹配適用於不一樣的場景,你們根據本身的需求進行選擇便可。學習

字符組

在正則表達式中,咱們常常會遇到從N個字符裏面選取任意字符進行匹配的需求。這個時候,咱們就須要一個字符組。具體示例以下:spa

const reg = /[abc]/; // 與上面示例徹底相同,匹配a或b或者c

當匹配的字符多了之後,咱們不可能所有都列到字符組裏,所以咱們可使用範圍表示法。具體示例以下:code

const reg = /[a-c]/; // 匹配a或b或c

相同類的字符能夠用範圍,如1-九、A-Z或者a-z。在字符組中,-是一個特殊字符,若是須要匹配-,則須要使用\進行轉義。cdn

固然,若是咱們是不想匹配N個字符中的任意一個,咱們能夠用排除字符組的方式來進行匹配。具體示例以下:ip

const reg = /[^abc]/; // 不匹配a、b、c中任意一個

排除字符組中也可使用範圍。字符串

量詞

當咱們須要匹配單個字符時,咱們可使用上面示例中的方法。可是,若是咱們須要匹配單個字符若干次呢?最簡單的方法就是將匹配的正則表達式寫若干次,可是這樣不只費時費力,還不方便閱讀。所以,正則表達式中使用了量詞來表示重複匹配N次的狀況。

量詞含義以下:

  • {m, },至少出現m次。
  • {m, n},最少出現m次,最多出現n次(最多出現N次的寫法爲{0, n},而不是{, n})
  • ,匹配0或者1次
  • +,最少匹配1次,與{1, }等價
  • *,匹配任意次,與{0, }等價

瞭解了上述量詞,下面咱們來看下這些量詞在示例中究竟是如何應用的:

const reg1 = /a+/; //至少匹配一次a

const reg2 = /a?b*/; //匹配0或者1次a,再匹配任意次的b

如今問題來了,上面示例中的/a+/這個正則表達式,若是遇到了字符串'aaa',那麼獲得的匹配結果是什麼呢?這個就涉及到了咱們下一節要介紹的內容。

貪婪匹配與非貪婪匹配

貪婪匹配:全部的量詞都會盡量多的進行匹配,默認值。以/a+/'aaa'爲例,匹配的結果是'aaa'
非貪婪匹配:全部的兩次都會盡量少的匹配。以/a+?/'aaa'爲例,匹配的結果是'a'

由於貪婪匹配是默認值,因此當咱們寫正則表達式時,默認就是貪婪匹配。那麼咱們應該如何來表示非貪婪匹配呢?具體示例以下:

const reg1 = /a+/; //貪婪匹配

const reg2 = /a+?/; // 非貪婪匹配

經過上面的示例咱們能夠看到,咱們只須要在兩次後加上一個?,就表示是一個非貪婪匹配。

注:非貪婪匹配只會向後做用,不會向前做用。即/a+?bb/匹配'aabb'是'aabb',而不是'abb';而/aab+?/則是匹配'aab'。(這個與正則表達式匹配和回溯的原理有關,有興趣的能夠閱讀個人下一篇關於正則表達式的博客)

分支邏輯

在一個正則表達式中,咱們會遇到作選擇的狀況。單個元素進行選擇時,咱們可使用字符組。可是,若是須要多個元素好比ab或者cd進行選擇時,這個時候咱們就須要分支邏輯。具體示例代碼以下:

const reg = /ab|cd/; //表示選擇ab或者cd。爲何不是b和c呢?這個咱們在下一篇博客——進階篇中將會講述操做符優先級問題。

位置匹配

正則表達式除了捕獲字符,還能夠捕獲字符串中的位置。所謂的位置,指的就是兩個字符之間。好比'ab'這個字符串,就有3個位置,分別位於a前面、a後面b前面和b後面。若是咱們將位置當成是一個空字符串'',其實對於位置的匹配也能夠概括到對字符的匹配中。

匹配位置的方式也有很多,咱們來看下:

  • ^,匹配開頭,多行模式下匹配行開頭,即每行開頭都會被匹配。
  • $,匹配結尾,多行模式下匹配行結尾,即每行結尾都會被匹配。
  • \b\w\W之間的位置(\w表示[0-9A-Za-z],而\W就是\w的補集),包括開頭結尾(即也包括\w^之間的位置,和\w$之間的位置)
  • \B,與\b相反,\w\w之間的位置,和\W\W之間的位置,包括開頭結尾(相對的,即包括\W^之間的位置,和\W$之間的位置)
  • (?=p),正向確定斷言。p是一個子模式,匹配要在p這個模式以前的位置
  • (?!p),正向否認斷言。與(?=p)相反,匹配不要在p這個模式以前的位置

上面說了這麼多,下面咱們經過一個示例來一下:

const reg1 = /^ab/; //對於字符串'abab'來講,只會匹配到開頭的'ab'
const reg2 = /ab$/; //對於字符串'abab'來講,只會匹配到結尾的'ab'
const reg3 = /\b/; //對於字符串'a b'來講,會匹配到'a'前面的位置、'a'和' '之間的位置、' '和'b'之間的位置、'b'後面的位置
const reg4 = /\B/; //對於字符串'aa bb[/來講,會匹配到'a'和'a'之間的位置、'b'和'b'之間的位置、'['後面的位置
const reg5 = /(?=a)/; //對於字符串'bac'來講,會匹配到'a'以前的位置
const reg6 = /(?!a)/; //對於字符串'bac'來講,會匹配到'b'以前的位置、'c'以前的位置以及'c'以後的位置

經過上面的例子,你們應該可以理解正則表達式在捕獲位置時候所發揮的做用。

ES2018新特性

在ES2018中,增長了反向確定斷言反向否認斷言。具體格式以下:

  • (?<=p),反向確定斷言。p是一個子模式,匹配要在p模式以後的位置
  • (?<!p),反向否認斷言。與(?<=p)相反,匹配不要在p模式以後的位置

咱們經過一個具體的示例來看下:

const reg1 = /(?<=a)b/ //對於字符串'abb'來講,只會匹配到'a'和'b'之間的位置。
const reg2 = /(?<=a)b/ //對於字符串'abb'來講,會匹配到'b'和'b'之間的位置。

括號與捕獲組

在正則表達式中,括號是一個功能很是多的操做符。本章咱們將會詳細介紹正則表達式中的括號的各類做用。

提升優先級

在正則表達式中,運算符操做也有優先級之分,以下例所示:

const reg1 = /ab|cd/; //匹配'ab'或者'cd'
const reg2 = /a(b|c)d/;//匹配'a'後,匹配一個'b'或者'c',再匹配一個'd'

關於正則表達式優先級相關的討論,咱們在此就不作展開了,有興趣的同窗能夠閱讀個人後一篇關於正則表達式高級進階的文章。

捕獲組與非捕獲組

若是咱們在正則表達式中,咱們須要獲取特定的匹配內容,那麼咱們就要用到捕獲組。捕獲組一般使用(p),其中p是一個子模式,表示須要捕獲的內容。具體使用示例以下:

const reg = /a(bc)d/;

let result = 'abcd'.match(reg); // 獲得的result[1]就是第一個捕獲組匹配的字符'ab'

可是,若是咱們在一些須要保證優先級的地方使用了小括號,可是又不想成爲捕獲組來干擾匹配,咱們應該怎麼辦呢?這個時候咱們就須要非捕獲組。咱們只須要在括號最開始加上一個?便可。具體使用示例以下:

const reg = /a(?:bc)d/;

let result = 'abcd'.match(reg); // 獲得的result沒有捕獲組

反向引用

當咱們在正則表達式中須要使用前面捕獲組匹配的內容時,咱們可使用反向引用。這在匹配一些成對的字符如'"等時很是有效。具體使用方式以下:

const reg = /(a)b\1/; //匹配字符'aba'

這裏須要注意的有三點:

  1. 若是出現括號嵌套的狀況,那麼從左到右以第一個括號(即左開括號)的順序爲準。
  2. \10表示的含義爲第10個捕獲組,而不是第一個捕獲組加上一個字符0。須要表示後者能夠用/(\1)0/。即便是在第三種狀況下,轉移符優先級仍然高於字符順序。
  3. 若是在正則表達式中出現的捕獲組個數小於使用的捕獲組,那麼\字符就會被當成一個轉移符而非反向引用。注:\2表示對2進行轉義的話,不一樣的瀏覽器對轉義後的結果是不同的。下圖是Chrome瀏覽器轉義後的結果

AuHfJMt8_gSEKoZe0R8uK8nzMZXNm96_7XRcdn2zX5NnfFSDJIWuKQ9d-iD2WTAgJQ?filename=image.png

總結

經過閱讀本文,你已經學到了正則表達式的最基礎的語法和使用規則。若是你想提升正則表達式的效率,加快正則表達式的閱讀和理解,能夠閱讀正則表達式系列第二篇文章。

相關文章
相關標籤/搜索