29.22分鐘學會書寫正則

寫在最前面

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

正則表達式

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

RegExp對象

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

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

正則可視化工具

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

元字符

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

  • 原義字符
  • 元字符

原義字符,就是表示本來意思的字符,像上面正則中的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"

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

再來看看一個問題,若是我只要開頭部分的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,咱們就可使用元字符 []來構建一個簡單的類
[abc]就把a,b,c歸爲一類,表示能夠匹配a或者b或者c。
若是你會一丟丟英文的話,你應該就能夠看懂下面的圖,one of abc,也就是匹配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"

前瞻/後顧

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 我想你應該知曉用法了

分組

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

hello{3}

而後你打開可視化工具

clipboard.png

媽耶,竟然只重複了個人o字母!死渣則,好過度

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

clipboard.png

分組之後怎麼使用分組內容呢?
首先看一個問題,如何匹配8個不連續的數字?
若是你不使用分組,你會發現根本無從下手,由於你不能判斷出有無重複!
咱們先公佈答案,再來分析一波

clipboard.png

  • 首先,這個(?!負向前瞻斷言A)表達式B,這裏使用的是負向前瞻,也就是說斷言A前面的內容(表達式B),不能符合表達式A,這個說法很拗口,我嘴巴都拗不過來了。能聽明白吧,這個設計就是,我這個斷言是「出現重複的數字」,而後表達式是「8個數字」,」8個數字「不能複合「出現重複的數字"
  • 而後,這個 .*(\d).* 呢,是先找到一個在任意位置出現的數字,爲何是任意位置呢?由於咱們判斷的重複可能出如今任何位置;看上面的可視化也就能夠明白,\d先後有0-n個字符,因此說他是任意位置的
  • 最關鍵的來了,這個\1表明什麼呢?仔細看你能夠發現,\d加了一個括號,這個括號就表明着分組,那麼是幾號分組呢?第一個括號就是分組1(默認狀況下),若是還有第二個括號,那就是分組2,前瞻的括號是不算的噢,而這個\1呢就表明着引用這個分組1,使用\2引用分組2。你也許會好奇,我引用它是至關於在這個位置寫了一個\d嗎?NOP,不只僅這麼簡單,它引用的是這個\d的內容,也就是說他會和\d是同樣的值!這不就是重複了嗎?!!!這個 .*(\d).*\1 就表明着任意位置出現了任意次數的重複
  • 最後,咱們把這些整合在一塊兒就是,匹配8個數字不能出現任意的重複。(?!出現任意重複)8個數字,由於這個(?!)是負向前瞻,因此。。。emmm。。這樣就理解了吧。

分組還有其餘更詳細的內容,可是篇幅有限,立刻就到30分鐘了。只好撿一些有價值經常使用的講了~

嘿嘿嘿

正則就介紹到這裏啦~
下篇文章將介紹javascript中的正則對象的屬性,以及一些方法。
29.22分鐘學會書寫正則(2)
若是有意見或者建議,請在評論區中指出,謝謝


  1. fnrtv
相關文章
相關標籤/搜索