29.22分鐘學會書寫正則

寫在最前面

看到標題你可能會疑惑爲什麼不是30分鐘?
因爲我這個文章圖文並茂,非常恐怖,兄弟,其實你不用30分鐘就可以看懂。
你可能會以爲我在吹牛B,但是當你看完的時候,一掐表,你會發現
我真的是在吹牛B
那又爲什麼是.22呢?
作爲一個理科生,保留兩位小數是不變的信仰。
而在下,僅僅是喜歡2這個數字,如是而已

正則表達式

正則表達式,又稱規則表達式。(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表達式通常被用來檢索、替換、校驗那些符合某個模式(規則)的文本。

RegExp對象

在爪窪死苦瑞per特中,RegExp 對象表示正則表達式,它是對字符串執行模式匹配的強大工具。
那麼要如何使用呢?
兩種方式:字面量,構造函數

var reg = /\bhello\b/g  //字面量 
// \b代表單詞邊界(WordBoundary) 也就是說這個正則匹配的是 hello world這種hello 而不是helloworld
//因爲helloworld連起來了,沒有單詞邊界
var reg = new RegExp('\\bhello\\b','g')
//注意兩者的區別
//後面這種方法需要轉義反斜槓(javascript的原因),
//而且這個g(修飾符)是單獨提取出來的
//而且正則兩邊沒有/包圍的,上面第一種是這樣的=> /正則表達式/

正則可視化工具

Regulex
可視化圖形,對理解正則有非常的幫助
二話不說先進來這個網站,這個文章將使用這個網站來驗證寫的例子。

元字符

正則表達式由兩種基本字符類組成

  • 原義字符
  • 元字符

原義字符,就是表示原本意思的字符,像上面正則中的hello,就代表匹配hello這個字符串
元字符呢,就是表示不是原本意思的字符,這樣想就簡單多了吧。像上面這個\b

clipboard.png

clipboard.png

既然元字符表示的不是本事的字符,那我如果就要匹配它原本的字符呢?比如說我就要匹配+號,*號,那麼請使用 \ 來轉義字符

下面這些元字符先隨便過一遍先,不用背熟也可往下看~

  • $ 匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 'n' 或 'r'。要匹配 $ 字符本身,請使用 \$。
  • () 標記一個子表達式的開始和結束位置。子表達式可以獲取供以後使用。要匹配這些字符,請使用 ( 和 )。
  • * 匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 *。
  • + 匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 +。
  • . 匹配除換行符 n 之外的任何單字符。要匹配 . ,請使用 . 。
  • [] 標記一箇中括號表達式的開始。要匹配 [,請使用 [。
  • {} 標記限定符表達式的開始。要匹配 {,請使用 {。
  • | 指明兩項之間的一個選擇。要匹配 |,請使用 |。
  • ? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 ?。
  • \ 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'n' 匹配換行符。序列 '\' 匹配 "",而 '(' 則匹配 "("。
  • ^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 ^。
  • \cX 匹配由x指明的控制字符。例如, cM 匹配一個 Control-M 或回車符。x 的值必須爲 A-Z 或 a-z 之一。否則,將 c 視爲一個原義的 'c' 字符。
  • \f 匹配一個換頁符。等價於 x0c 和 cL。
  • \n 匹配一個換行符。等價於 x0a 和 cJ。
  • \r 匹配一個回車符。等價於 x0d 和 cM。
  • \s 匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ fnrtv]。注意 Unicode 正則表達式會匹配全角空格符。
  • \S 匹配任何非空白字符。等價於 1
  • \t 匹配一個製表符。等價於 x09 和 cI。
  • \v 匹配一個垂直製表符。等價於 x0b 和 cK

邊界

clipboard.png

從一開始的例子我們就知道了這個b,不對,是這個\b
他表示的就是單詞邊界的意思.
我們知道,f*ck這個是有很多用法的,可以單獨用,也可以加個ing多種詞性使用。
然後我們只想找到單獨的f*ck,看代碼

//作爲光榮的社會主義接班人怎麼可能用f*ck做例子呢?
var reg = /\bis\b/g;
var str = "this is me";
str.replace(reg,'X')
//"this X me"
var reg = /is/g;
var str = "this is me";
str.replace(reg,'X')
//"thX X me"

兩者區別清晰可見,不容我多說了吧,各位客官。

再來看看一個問題,如果我只要開頭部分的A字符而文本中間的A字符卻不要,又該如何?
只需如此,便可對敵

var reg = /^A/g;
var str = "ABA";
str.replace(reg,'X');
//"XBA"

clipboard.png

需要以A爲結尾的正則,則是如下

var reg = /A$/g;
var str = "ABA";
str.replace(reg,'X');
//"ABX"

clipboard.png

注意,正如開頭結尾的位置一樣,^和$的位置也是如此,^放在正則表達式前面,$放在表達式後面

字符類

一般情況下,正則表達式一個字符對應字符串的一個字符
比如表達式 \bhello 就表示 匹配 字符\b h e l l o,

如果我們想要匹配一類字符的時候?
比如我要匹配a或者b或者c,我們就可以使用元字符 []來構建一個簡單的類
[a,b,c]就把a,b,c歸爲一類,表示可以匹配a或者b或者c。
如果你會一丟丟英文的話,你應該就可以看懂下面的圖,one of a,b,c,也就是匹配abc中任意一個~

clipboard.png

範圍類

當我們學習了上面的內容以後,如果我們要寫匹配0到9的數字,就應該是這樣寫

clipboard.png

但是如果我要匹配更多呢?那不是鍵盤都要敲爛了?這正則也太不智能了吧???
顯然,你能想到的,創造正則的人也想到了
我們可以這樣子

clipboard.png

好了,方便了一些,然後你可能又會吃驚,那麼我的短橫線-呢?我如果要匹配0-9以及短橫線呢?
莫慌,只要在後面補回去即可
這個圖可以清楚看到有兩條分支,也就是說我可以走0-9這條路也可以走短橫線這條路

clipboard.png

clipboard.png

預定義類

學習了上面以後,我們就可以書寫匹配數字的正則了,[0-9]

那麼有沒有更簡便更短的方法呢?

巧了,正則就是辣麼強大

在上面的元字符部分內容中,你可能已經窺得其中精妙了

上表格,不是,上圖(這個segmentfault哪裏插入表格啊??)

clipboard.png

clipboard.png

clipboard.png

clipboard.png

clipboard.png

我們可以根據英文單詞的意思,來記住這些預定義類的用法。
我們發現,大寫字母和小寫字母的區別就是取反!,如d和D
同時我們從表格中的等價類可以發現如果我們要一個類的取反,那麼就在類中加一個 ^
none of abc

clipboard.png

量詞

如果要你寫一個匹配10個數字的正則?你會怎麼寫
誒~你可能已經胸有成竹的寫下了

\d\d\d\d\d\d\d\d\d\d

吃驚,你會發現,儘管是你單身二十餘年的右手,依然感到了一絲乏力!
疲憊,有時是在過度勞累之後
爲了挽救一些人的右臂,正則有了量詞
實現上面的需求我們只要 \d{10}
clipboard.png

Digit 10times
爲了方便一些英語不好的人,比如我,我甚至使用了鮮爲人知的百度翻譯(廣告費私我)

clipboard.png

但是,如果我不知道要匹配具體多少個數字呢?反正就是匹配100個到1000個之間的數字
噹噹噹當~

clipboard.png

讓我們看看可視化工具的結果,方便理解

注意,這個{n,m}是包括n次和m次的哦,是閉區間哦

clipboard.png

貪婪模式與非貪婪模式

從上面一則我們知道,如果我們要匹配100到1000個數字的話,是這樣寫
\d{100,1000}
如果我給的字符串裏有1000個數字,但是我只想匹配前面100個呢?

如果按照上面這樣寫,則如下

var reg = /\d{3,6}/;
var str = "123456789";
str.replace(reg,'替換成這個');
//"替換成這個789"

我們可以看到,上面這個例子是匹配了6個數字,將6個數字替換了,儘管他的正則匹配的是3到6個數字。

沒錯,它是貪婪的!它會儘可能地匹配更多!
這就是正則的 貪婪匹配,這是默認的,如果我們不想要那麼貪婪,如何變得容易滿足一點?
只需要在量詞後面加上 ? 即可

var reg = /\d{3,6}?/;
var str = "123456789";
str.replace(reg,'替換成這個');
//"替換成這個456789"

可以清楚看到正則只匹配了前面3個數字~這就是正則的非貪婪模式

分支條件

如果我只需要匹配100個或者1000個數字呢?
就只有100和1000兩種可能,而不是100到1000任意一個數字,又該如何對敵?
這就要設計到正則的分支條件了

\d{100}|\d{1000}

clipboard.png

需要注意的是這個 | 分割的是左右兩邊所有部分,而不是僅僅連着這個符號的左右兩部分,看下圖

clipboard.png

有時候我們只需要一部分是分支,後面走的是同一條主幹,只需要把分支用()包含即可

clipboard.png

注意:這個匹配是從正則左邊的分支條件開始的,如果左邊滿足了,那麼右邊就不會在對比!

var reg = /\d{4}|\d{2}/
var str = "12345"
str.replace(reg,'X');
// "X5"
var reg = /\d{2}|\d{4}/
var str = "12345"
str.replace(reg,'X');
//"X345"

分組

當我們要匹配一個出現三次的單詞而不是數字的時候,會怎麼寫呢?
你可能會這樣寫

hello{3}

然後你打開可視化工具

clipboard.png

媽耶,居然只重複了我的o字母!死渣則,好過分

其實,我們只要使用()就可以達到分組的目的,使量詞作用於分組,上面分支條件中的括號亦是如此

clipboard.png

前瞻/後顧

sometimes,我們要找尋的字符可能還要依靠前後字符來確定
比如說我要替換連續的2個數字,而且它的前面要連着是2個英文字母,這樣的數字我纔要
你可能會疑惑,這樣寫不就完事了嗎?

\d{2}\w{2}

上面匹配的是2個數字和2個字母,雖然是連着的,但是匹配了是4個字符,如果我要替換匹配文本的話,那就替換了4個字符,而我們只想替換2個數字!
這個時候就需要用到斷言了
首先我們需要明白幾個點

  • 正則表達式從文本頭部到尾部開始解析,文本尾部方向叫做‘前’,也就是往前走,就是往尾巴走
  • 前瞻就是正則表達式匹配到規則(此例中的‘2個數字’)的時候,向前看看,看看是否符合斷言(此例中的‘前面連着2個字母’),後瞻/後顧的規則則相反。(javascript不支持後顧)

上表格!

clipboard.png

根據表格內容,我們就可以解決這個問題了,注意\w包括數字哦~題目要求是連着2個字母

clipboard.png

var reg = /\d{2}(?=[a-zA-Z]{2})/;
var str = "1a23bc456def";
str.replace(reg,'X');
//"1aXbc456def"

只替換了數字,沒有替換後面的斷言哦!

順便把這個負向前瞻看看吧

clipboard.png

看到這個not followed by 我想你應該知曉用法了

嘿嘿嘿

正則就介紹到這裏啦~
下篇文章將介紹javascript中的正則對象的屬性,以及一些方法。
如果有意見或者建議,請在評論區中指出,謝謝


  1. fnrtv
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章