一文掌握正則表達(dá)式

一、前言

有的小伙伴對(duì)正則有所懼怕,也有的小伙伴遇到正則就搜索答案。其實(shí)這些都是正常的,不論是剛從事前端、還是從業(yè)好幾年的小伙伴。如果沒(méi)有專門去學(xué)習(xí)下正則表達(dá)式,沒(méi)掌握很正常的。

預(yù)熱
.match(/(?<=\/detail.*\/)[^\/]+/)[0]

/^(([1-9]\d*)|\d)(\.\d{1,6})?$/

"hello qianduan zaocha".match(/\b[a-z]+(?=a\b)/g)
如果看得明白上面的正則,本文可以跳著閱讀,如果看得不是特別明白,建議按順序閱讀~
二、JS中運(yùn)行正則

正則表達(dá)式,又稱規(guī)則表達(dá)式,(在代碼中常簡(jiǎn)寫為regex、regexp或RE),是一種文本模式,是計(jì)算機(jī)科學(xué)的一個(gè)概念。

JavaScript中使用String對(duì)象和RegExp對(duì)象提供的方法來(lái)運(yùn)行正則表達(dá)式。
RegExp對(duì)象的方法

exec(): array
exec()方法返回正則執(zhí)行一次的結(jié)果。如果設(shè)置了全局標(biāo)志g,會(huì)返回一個(gè)捕獲組,用于迭代執(zhí)行。且這個(gè)捕獲組的第一項(xiàng)是當(dāng)前完整正則的一次執(zhí)行結(jié)果,第二項(xiàng)開(kāi)始是每一個(gè)子模式的執(zhí)行結(jié)果。

test(): boolean
test()方法用于檢測(cè)傳入的字符串是否包含符合正則規(guī)則的子串,如果包含返回true,否則返回false。
String對(duì)象的方法

  重用的String對(duì)象方法大概有10來(lái)個(gè),正則里面一般使用其中的4個(gè)。

match()
match()方法接收一個(gè)正則對(duì)象,用來(lái)匹配調(diào)用字符串中符合規(guī)則的子串。如果正則對(duì)象添加了全局標(biāo)志,那么直接返回所有的匹配結(jié)果,否則,返回一個(gè)可以被迭代執(zhí)行的捕獲組 。

replace()
replace()方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是用來(lái)匹配調(diào)用字符串的正則表達(dá)式(字符串會(huì)被轉(zhuǎn)化成簡(jiǎn)單模式的正則規(guī)則),第二個(gè)參數(shù)表示要替換的字符串或者返回字符串的函數(shù)。replace()方法不改變?cè)醋址?br>
search()
search()方法接收一個(gè)正則對(duì)象或一個(gè)字符串(字符串會(huì)轉(zhuǎn)換成簡(jiǎn)單模式的正則表達(dá)式),用來(lái)查找調(diào)用字符串中符合規(guī)則的子串的位置,匹配到了就返回第一次出現(xiàn)的索引,否則返回-1

split()
split()方法接收兩個(gè)參數(shù),第一個(gè)是一個(gè)正則或字符串,表示將要匹配并用于切分的字符,使用第一個(gè)參數(shù)匹配調(diào)用字符串,在符合規(guī)則的位置將字符串切分未為數(shù)組,并返回。第二個(gè)參數(shù)限制分割的片段數(shù)量。
三、簡(jiǎn)單的規(guī)則

1: 一般寫正則表單時(shí),都是先按如下,把格式定好
/^    $/
溫馨提示:正則表達(dá)式是很精確的,不要有多余的空格

2. 正則表達(dá)式定義
正則表達(dá)式是用來(lái)匹配一串文本中符合規(guī)則的子串的字符組合。一段用于匹配的正則表達(dá)式通常稱為一個(gè)模式。

3、正則是區(qū)分大小寫的
在正則規(guī)則里面,大寫往往是"非"。比如:\d,匹配數(shù)字。\D 匹配非數(shù)字。
四、元字符

概念:所謂元字符就是指那些在正則表達(dá)式中具有特殊意義的專用字符,可以用來(lái)規(guī)定其前導(dǎo)字符(即位于元字符前面的字符)在目標(biāo)對(duì)象中的出現(xiàn)模式。






元字符的完整列表

字符    描述
\   
將下一個(gè)字符標(biāo)記為一個(gè)特殊字符、或一個(gè)原義字符、或一個(gè) 向后引用、或一個(gè)八進(jìn)制轉(zhuǎn)義符。例如,'n' 匹配字符 "n"。'\n' 匹配一個(gè)換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。
^   
匹配輸入字符串的開(kāi)始位置。如果設(shè)置了 RegExp 對(duì)象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$   
匹配輸入字符串的結(jié)束位置。如果設(shè)置了RegExp 對(duì)象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。
*   
匹配前面的子表達(dá)式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價(jià)于{0,}。
+   
匹配前面的子表達(dá)式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價(jià)于 {1,}。
?   
匹配前面的子表達(dá)式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 。? 等價(jià)于 {0,1}。
{n}   
n 是一個(gè)非負(fù)整數(shù)。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個(gè) o。
{n,}   
n 是一個(gè)非負(fù)整數(shù)。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價(jià)于 'o+'。'o{0,}' 則等價(jià)于 'o*'。
{n,m}   
m 和 n 均為非負(fù)整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個(gè) o。'o{0,1}' 等價(jià)于 'o?'。請(qǐng)注意在逗號(hào)和兩個(gè)數(shù)之間不能有空格。
?   
當(dāng)該字符緊跟在任何一個(gè)其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面時(shí),匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對(duì)于字符串 "oooo",'o+?' 將匹配單個(gè) "o",而 'o+' 將匹配所有 'o'。
.   
匹配除換行符(\n、\r)之外的任何單個(gè)字符。要匹配包括 '\n' 在內(nèi)的任何字符,請(qǐng)使用像"(.|\n)"的模式。
(pattern)   
匹配 pattern 并獲取這一匹配。所獲取的匹配可以從產(chǎn)生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號(hào)字符,請(qǐng)使用 '\(' 或 '\)'。
(?:pattern)   
匹配 pattern 但不獲取匹配結(jié)果,也就是說(shuō)這是一個(gè)非獲取匹配,不進(jìn)行存儲(chǔ)供以后使用。這在使用 "或" 字符 (|) 來(lái)組合一個(gè)模式的各個(gè)部分是很有用。例如, 'industr(?:y|ies) 就是一個(gè)比 'industry|industries' 更簡(jiǎn)略的表達(dá)式。
(?=pattern)   
正向肯定預(yù)查(look ahead positive assert),在任何匹配pattern的字符串開(kāi)始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說(shuō),該匹配不需要獲取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。預(yù)查不消耗字符,也就是說(shuō),在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開(kāi)始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開(kāi)始。
(?!pattern)   
正向否定預(yù)查(negative assert),在任何不匹配pattern的字符串開(kāi)始處匹配查找字符串。這是一個(gè)非獲取匹配,也就是說(shuō),該匹配不需要獲取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。預(yù)查不消耗字符,也就是說(shuō),在一個(gè)匹配發(fā)生后,在最后一次匹配之后立即開(kāi)始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開(kāi)始。
(?<=pattern)    反向(look behind)肯定預(yù)查,與正向肯定預(yù)查類似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。
(?<!pattern)    反向否定預(yù)查,與正向否定預(yù)查類似,只是方向相反。例如"(?<!95|98|NT|2000)Windows"能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"。
x|y   
匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。
[xyz]   
字符集合。匹配所包含的任意一個(gè)字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz]   
負(fù)值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'、'l'、'i'、'n'。
[a-z]   
字符范圍。匹配指定范圍內(nèi)的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范圍內(nèi)的任意小寫字母字符。
[^a-z]   
負(fù)值字符范圍。匹配任何不在指定范圍內(nèi)的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范圍內(nèi)的任意字符。
\b   
匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B   
匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx   
匹配由 x 指明的控制字符。例如, \cM 匹配一個(gè) Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個(gè)原義的 'c' 字符。
\d   
匹配一個(gè)數(shù)字字符。等價(jià)于 [0-9]。
\D   
匹配一個(gè)非數(shù)字字符。等價(jià)于 [^0-9]。
\f   
匹配一個(gè)換頁(yè)符。等價(jià)于 \x0c 和 \cL。
\n   
匹配一個(gè)換行符。等價(jià)于 \x0a 和 \cJ。
\r   
匹配一個(gè)回車符。等價(jià)于 \x0d 和 \cM。
\s   
匹配任何空白字符,包括空格、制表符、換頁(yè)符等等。等價(jià)于 [ \f\n\r\t\v]。
\S   
匹配任何非空白字符。等價(jià)于 [^ \f\n\r\t\v]。
\t   
匹配一個(gè)制表符。等價(jià)于 \x09 和 \cI。
\v   
匹配一個(gè)垂直制表符。等價(jià)于 \x0b 和 \cK。
\w   
匹配字母、數(shù)字、下劃線。等價(jià)于'[A-Za-z0-9_]'。
\W   
匹配非字母、數(shù)字、下劃線。等價(jià)于 '[^A-Za-z0-9_]'。
\xn   
匹配 n,其中 n 為十六進(jìn)制轉(zhuǎn)義值。十六進(jìn)制轉(zhuǎn)義值必須為確定的兩個(gè)數(shù)字長(zhǎng)。例如,'\x41' 匹配 "A"。'\x041' 則等價(jià)于 '\x04' & "1"。正則表達(dá)式中可以使用 ASCII 編碼。
\num   
匹配 num,其中 num 是一個(gè)正整數(shù)。對(duì)所獲取的匹配的引用。例如,'(.)\1' 匹配兩個(gè)連續(xù)的相同字符。
\n   
標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用。如果 \n 之前至少 n 個(gè)獲取的子表達(dá)式,則 n 為向后引用。否則,如果 n 為八進(jìn)制數(shù)字 (0-7),則 n 為一個(gè)八進(jìn)制轉(zhuǎn)義值。
\nm   
標(biāo)識(shí)一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用。如果 \nm 之前至少有 nm 個(gè)獲得子表達(dá)式,則 nm 為向后引用。如果 \nm 之前至少有 n 個(gè)獲取,則 n 為一個(gè)后跟文字 m 的向后引用。如果前面的條件都不滿足,若 n 和 m 均為八進(jìn)制數(shù)字 (0-7),則 \nm 將匹配八進(jìn)制轉(zhuǎn)義值 nm。
\nml   
如果 n 為八進(jìn)制數(shù)字 (0-3),且 m 和 l 均為八進(jìn)制數(shù)字 (0-7),則匹配八進(jìn)制轉(zhuǎn)義值 nml。
\un   
匹配 n,其中 n 是一個(gè)用四個(gè)十六進(jìn)制數(shù)字表示的 Unicode 字符。例如, \u00A9 匹配版權(quán)符號(hào) (?)。

上面這個(gè)表是完整的元字符,下面列舉幾個(gè)常用的展開(kāi)講講:
“點(diǎn)號(hào)”
/./.exec('liangzai')   // l

“轉(zhuǎn)義運(yùn)算符“
/\//.exec('前//端/早茶')   // /
“字符集“
/[liangzai]/.exec('qdzc')   // z
匹配方括號(hào)內(nèi)的任意字符

“位置“
/^\//.exec('//前/端/早/茶')   // /
開(kāi)頭
/\/$/.exec('前端/早茶//')   // /
結(jié)尾

“文本控制字符“
\f  匹配一個(gè)換頁(yè)符
\n 匹配一個(gè)換行符
\r 匹配一個(gè)回車符
五、標(biāo)記

標(biāo)記用來(lái)修改正則表達(dá)式的一些默認(rèn)行為,包括是否忽略大小寫(i),是否全局搜索(g),是否多行搜索(m)。
標(biāo)記不屬于元字符,因此不寫在正則規(guī)則里面,而是寫在規(guī)則后面。
i、g這兩個(gè)比較通用,廣東靚仔就不多講了。我們來(lái)看看這個(gè)m
`   
    qdzc#
    gdlz#
    omg!
`.match(/\w+(?=#)/gm)
// qdzc,gdlz
全局查詢,且多行查詢
Tips: 多行標(biāo)記m可以讓開(kāi)頭和結(jié)尾的標(biāo)記符^, $在多行使用
六、貪婪匹配、懶惰匹配

貪婪匹配:正則表達(dá)式趨向于最長(zhǎng)匹配。
懶惰匹配:正則表達(dá)式趨向于最短匹配(只匹配剛好滿足規(guī)則的子串)。
// 貪婪匹配
/\w+/.exec('qdzc_ q')   // qdzc_
 
// 惰性匹配
/\w+?/.exec('qdzc_ q')   // q
正則表達(dá)式默認(rèn)是貪婪匹配,會(huì)盡可能地匹配多的符合規(guī)則地字符。

正則表達(dá)式主要分兩個(gè)標(biāo)準(zhǔn):posix和pcre
posix是unix遵循的標(biāo)準(zhǔn)。grep,sed支持的正則是posix。
pcre在posix的基礎(chǔ)上做了擴(kuò)展,提供了很多方便的功能。

一段用于匹配的正則表達(dá)式通常稱為一個(gè)模式
七、零寬斷言


零寬:只匹配位置,不匹配內(nèi)容
斷言: 用來(lái)判斷某個(gè)字符的前后,是否符合某種特定格式。

零寬斷言種類
?= 正先行斷言。匹配符合規(guī)則的位置,先行,即匹配斷言規(guī)則前面的字符
?! 負(fù)先行斷言。匹配不符合規(guī)則的位置,先行,即匹配斷言規(guī)則前面的字符
?<= 正向 即匹配符合規(guī)則的位置,后發(fā),即匹配斷言規(guī)則后面的字符
?<! 反向 即匹配不符合規(guī)則的位置,后發(fā),即匹配斷言規(guī)則后面的字符

(?=exp):零寬度正預(yù)測(cè)先行斷言,它斷言自身出現(xiàn)的位置的后面能匹配表達(dá)式exp。
(?<=exp):零寬度正回顧后發(fā)斷言,它斷言自身出現(xiàn)的位置的前面能匹配表達(dá)式exp
(?!exp):零寬度負(fù)預(yù)測(cè)先行斷言,斷言此位置的后面不能匹配表達(dá)式exp。
(?<!exp):零寬度負(fù)回顧后發(fā)斷言來(lái)斷言此位置的前面不能匹配表達(dá)式exp


作者:廣東靚仔


歡迎關(guān)注:前端早茶