前端的正則表達(dá)式

正則的用法

  const regex = /abc/g
  const regex2 = new RegExp('abc', 'g')
  regex 和 regex2的匹配內(nèi)容是一樣的,都是全局匹配abc字符串刻蟹,
  只不過regex是用正則表達(dá)式字面量逗旁,而regex2是調(diào)用RegExp構(gòu)造函數(shù)寫法。

元字符

^   匹配字符串的開始               /^a/ 表示匹配以a開始
$   匹配字符串的結(jié)尾               /a$/ 表示匹配以a結(jié)尾
\d  [0-9] 表示0-9的任意一位數(shù)字    /^\d/ 表示以一個(gè)數(shù)字開始
\D  [^0-9] 表示除數(shù)字外的任意字符   /^\D/ 表示不能以數(shù)字開始
\w  [0-9a-zA-Z_] 表示數(shù)字舆瘪、大小寫字母和下劃線
\W  [^0-9a-zA-Z_] 表示非單詞字符
\s  [\t\v\n\r\f]片效。表示空白符,包括空格英古、水平制表符淀衣、垂直制表符、換行符召调、回車符膨桥、換頁符
\S  [^ \t\v\n\r\f] 非空白符
\b  匹配一個(gè)單詞邊界
\B  匹配非單詞邊界
.   [^\n\r\u2028\u2029]。通配符唠叛,表示幾乎任意字符只嚣。換行符、回車符玻墅、行分隔符和段分隔符除外介牙。
    要是想匹配字符串.需要轉(zhuǎn)譯\.

量詞

{m, n} 出現(xiàn)了m-n次
{m}    出現(xiàn)了m次
{m,}   出現(xiàn)了至少mci
{,n}   最多出現(xiàn)了n次
壮虫?     出現(xiàn)了0次或1次澳厢, 等價(jià)于{0,1}
+      最少出現(xiàn)了1次,等價(jià)于{1,}
*      出現(xiàn)0次或多次,等價(jià)于{0,}

貪婪與惰性

貪婪就是盡可能多的匹配囚似,而惰性就是盡可能少的匹配

貪婪匹配寫法:量詞后面加個(gè)*
惰性匹配寫法:量詞后面加個(gè)剩拢?

/.*bbb/g.exec('abbbaabbbaaabbb1234')  // abbbaabbbaaabbb
/.*?bbb/g.exec('abbbaabbbaaabbb1234') // abbb

貪婪模式用于匹配優(yōu)先量詞修飾的子表達(dá)式
惰性模式用于匹配忽略優(yōu)先量詞修飾子表達(dá)式

分組

正則中一對()即為一個(gè)分組

/(abx).*/.test('abxsss') 其中(abx) 就是一個(gè)分組

可使用構(gòu)造函數(shù)的全局屬性1至9來獲取

/(abx).*/.exec('abxsss')
console.log(RegExp.$1)  // abx
console.log(RegExp.$_)  // abxsss

只能表示到1-9, 如果分組超過了九組饶唤,那就沒法表示了

反向引用

/\d{4}(-|\/|\.)\d{2}\1\d{2}/
注意里面的\1徐伐,表示的引用之前的那個(gè)分組(-|\/|\.)。
不管它匹配到什么(比如-)募狂,\1都匹配那個(gè)同樣的具體某個(gè)字符办素。
我們知道了\1的含義后,那么\2和\3的概念也就理解了祸穷,即分別指代第二個(gè)和第三個(gè)分組性穿。

這里的分組只是在此之前的分組,在該反向引用之后的無法表示雷滚。
/\d{4}(-|\/|\.)\d{2}\2(\d{2})/
這里不能用\2來引用(\d{2})分組需曾,這里只是當(dāng)作匹配\2去匹配,而不是當(dāng)作分組的引用

具名分組

/(\d{4}(-|\/|\.))\d{2}\2\d{2}/
這里的第二個(gè)分組應(yīng)該是(-|\/|\.)

那/^((\d)(\d(\d)))$/的分組又是怎么分的呢?
對于過多括號嵌套情況呆万,分清分組比較容易出錯(cuò)
括號嵌套的分組商源,應(yīng)該從第一個(gè)(往里面數(shù),每遇到一個(gè)(就是一個(gè)新的分組

具名分組就很好的解決了這個(gè)問題
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
這里就是用到了具名分組
可以通過\k<month>引用具體是哪個(gè)分組
/(?<year>\d{4})-(?<month>\d{2})-\k<month>/
具名分組結(jié)果會(huì)放在group屬性里面

非捕獲分組

也可以通過非捕獲分組來降低分組的復(fù)雜度谋减。非捕獲分組是指不會(huì)將(?:)中的正則化為一個(gè)分組牡彻。
/^(?:(?:\d)(\d(\d)))\2$/
這里\2引用的分組是(\d)

零寬斷言(環(huán)視)和負(fù)零寬斷言

/z(?=x)y/ 表示z后面緊跟著的是x,但是不匹配x
/z(?!x)y/ 表示z后面緊跟著的不是x逃顶,但是不匹配x

/z(?<=x)y/ 表示y前面緊跟著的是x讨便,但是不匹配x
/z(?<!x)y/ 表示y前面緊跟著的不是x,但是不匹配x


修飾符

1. g → global 全局搜索
2. i → ignoreCase 忽略大小寫以政,大小寫不敏感
3. m → multiline 換行
4. y → sticky  “粘連”修飾符  后一次匹配都從上一次匹配成功的下一個(gè)位置開始
5. u → unicode Unicode 字符表示法

lastIndex

是正則表達(dá)式的一個(gè)可讀可寫的整型屬性霸褒,用來指定下一次匹配的起始索引。
只有正則表達(dá)式使用了表示全局檢索的 "g" 標(biāo)志時(shí)盈蛮,該屬性才會(huì)起作用废菱。此時(shí)應(yīng)用下面的規(guī)則:

如果 lastIndex 大于字符串的長度,則 regexp.test 和 regexp.exec 將會(huì)匹配失敗抖誉,然后 lastIndex 被設(shè)置為 0殊轴。
如果 lastIndex 等于字符串的長度,且該正則表達(dá)式匹配空字符串袒炉,則該正則表達(dá)式匹配從 lastIndex 開始的字符串旁理。(then the regular expression matches input starting at lastIndex.)
如果 lastIndex 等于字符串的長度,且該正則表達(dá)式不匹配空字符串 我磁,則該正則表達(dá)式不匹配字符串孽文,lastIndex 被設(shè)置為 0.。
否則夺艰,lastIndex 被設(shè)置為緊隨最近一次成功匹配的下一個(gè)位置芋哭。

練習(xí)


1.檢測是否滿足
  2016-06-12
  2016/06/12
  2016.06.12
  這三種格式


/\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/.test('2012/12/13')
這樣寫有一個(gè)問題,那就是
/\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/.test('2012/12-13') 也是true

所以這里就得用到分組引用了
/\d{4}(-|\/|\.)\d{2}\1\d{2}/.test('2012/12-13') false
/\d{4}(-|\/|\.)\d{2}\1\d{2}/.test('2012/12/13') true
這里的\1指的是第一個(gè)分組匹配到了什么郁副,這里就是什么


2.將 2016/12/04 改為 12/04/2016
傳統(tǒng)做法可能是需要先以'/'分割字符串减牺,然后在就行字符串拼接
現(xiàn)在可以這樣寫

'2016/12/04'.replace(/(\d{4})\/(\d{2})\/(\d{2})/, '$2/$3/$1')

或者

'2016/12/04'.replace(/(\d{4})\/(\d{2})\/(\d{2})/, function(...arg) {
  return arg[2]+'/' + arg[3]+'/' + arg[1]
})

let result = /(?<year>\d{4})\/(?<month>\d{2})\/(?<day>\d{2})/.exec('2016/12/04')
console.log(result)
// 0: "2016/12/04"
// 1: "2016"
// 2: "12"
// 3: "04"
// groups:
//  day: "04"
//  month: "12"
//  year: "2016"
// index: 0
// input: "2016/12/04" 


3.可以正確篩選以下規(guī)則
'x=5'           5
'abcx=5'        5
'abc x=5'       5
'x=abc'         null

str.match(/(?<=x=)\d+/)

4.可以正確篩選以下規(guī)則
'x=5'           5
'abcx=5'        null
'abc x=5'       5
'x=abc'         null
這個(gè)和上面的區(qū)別就在于x=之前是不是一個(gè)邊界
str.match(/(?<=\bx=)\d+/)
不可以用一下的正則匹配
str.match(/(?<=\s+x=)\d+/)
因?yàn)檫@樣的話'x=5'就不匹配了

5.可以正確篩選以下規(guī)則
'one "two three" four five six "seven eight" nine' 
to 
'"two three" four five six "seven eight"'

str.match(/".*"/g)

6.可以正確篩選以下規(guī)則
'one "two three" four five six "seven eight" nine' 
to 
['"two three"', '"seven eight"']

str.match(/".*?"/g)
這里和上面的區(qū)別就在于一個(gè)是貪婪匹配而這個(gè)是惰性匹配

7.可以正確篩選以下規(guī)則
'@@whatever@@@@whatever2@@' 
to
 '<blink>whatever</blink><blink>whatever2</blink>'

str.replace(/(@@)(.*?)(@@)/g, function(...arg) {
  return '<blink>'+ arg[2]+'</blink>'
})
這里不能簡單的將'@@'替換成'<blink>',因?yàn)?@@'必須是成對出現(xiàn)的

8.可以正確篩選以下規(guī)則
var text = "First line\nsecond line";
var regex = /(\S+) line\n?/y;

var match = regex.exec(text);
match[1];  // "First"

var match2 = regex.exec(text);
match2[1]// "Second"

var match3 = regex.exec(text);
match3 === null //"true"
這里是開啟粘滯匹配的一個(gè)事例

9.測試以下代碼
var re=/^\w$/g
re.test('a')  true
re.test('a')  false
re.test('a')  true
re.test('a')  false
re.test('a')  true
re.test('a')  false
re.test('a')  true
re.test('a')  false
...

為什么會(huì)出現(xiàn)這種情況呢?
這里就涉及到了lastIndex了存谎,
var re=/^\w$/g
re.lastIndex = 0

re.test('a')  true
這里正則匹配完成后re.lastIndex = 1

re.test('a')  false
因?yàn)閞e.lastIndex = 1了拔疚,所以這里的re.test就會(huì)失效,當(dāng)然re.exec也會(huì)失效既荚。
可以理解為這時(shí)正則是從1這個(gè)位置去匹配的稚失,所以匹配不到任何東西.只會(huì)就會(huì)再次把lastIndex改為0
re.lastIndex = 0

re.test('a')  true
又重新從頭開始匹配了,所以這里又再次為true了

結(jié)尾

本文并沒有舉例傳統(tǒng)的一下正則固以,如郵箱格式墩虹,手機(jī)號碼格式等嘱巾,因?yàn)檫@些正則可以搜到很多。本文主要是用到了一下稍微高階一點(diǎn)的正則方法诫钓。古人云:用好了正則旬昭,可以幫我們省下5000行代碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末菌湃,一起剝皮案震驚了整個(gè)濱河市问拘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惧所,老刑警劉巖骤坐,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異下愈,居然都是意外死亡纽绍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門势似,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拌夏,“玉大人,你說我怎么就攤上這事履因≌喜荆” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵栅迄,是天一觀的道長站故。 經(jīng)常有香客問我,道長毅舆,這世上最難降的妖魔是什么西篓? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮朗兵,結(jié)果婚禮上污淋,老公的妹妹穿的比我還像新娘顶滩。我一直安慰自己余掖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布礁鲁。 她就那樣靜靜地躺著盐欺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仅醇。 梳的紋絲不亂的頭發(fā)上冗美,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機(jī)與錄音析二,去河邊找鬼粉洼。 笑死节预,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的属韧。 我是一名探鬼主播安拟,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宵喂!你這毒婦竟也來了糠赦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤锅棕,失蹤者是張志新(化名)和其女友劉穎拙泽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裸燎,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顾瞻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了德绿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朋其。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖脆炎,靈堂內(nèi)的尸體忽然破棺而出梅猿,到底是詐尸還是另有隱情,我是刑警寧澤秒裕,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布袱蚓,位于F島的核電站,受9級特大地震影響几蜻,放射性物質(zhì)發(fā)生泄漏喇潘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一梭稚、第九天 我趴在偏房一處隱蔽的房頂上張望颖低。 院中可真熱鬧,春花似錦弧烤、人聲如沸忱屑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莺戒。三九已至,卻和暖如春急波,著一層夾襖步出監(jiān)牢的瞬間从铲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工澄暮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留名段,地道東北人阱扬。 一個(gè)月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像伸辟,于是被迫代替她去往敵國和親价认。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容