国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

《JavaScript 正則表達(dá)式迷你書(shū)》知識(shí)點(diǎn)小抄本

zollero / 955人閱讀

摘要:介紹這周開(kāi)始學(xué)習(xí)老姚大佬的正則表達(dá)式迷你書(shū),然后習(xí)慣性的看完一遍后,整理一下知識(shí)點(diǎn),便于以后自己重新復(fù)習(xí)。感謝原書(shū)作者老姚,本文無(wú)意抄襲,只是作為自己知識(shí)點(diǎn)的整理,后續(xù)也會(huì)整理到自己的知識(shí)庫(kù)網(wǎng)站中。等價(jià)于,表示出現(xiàn)次。

介紹

這周開(kāi)始學(xué)習(xí)老姚大佬的《JavaScript 正則表達(dá)式迷你書(shū)》 , 然后習(xí)慣性的看完一遍后,整理一下知識(shí)點(diǎn),便于以后自己重新復(fù)習(xí)。

我個(gè)人覺(jué)得:自己整理下來(lái)的資料,對(duì)于知識(shí)重現(xiàn),效果不錯(cuò)。

感謝原書(shū)作者老姚,本文無(wú)意抄襲,只是作為自己知識(shí)點(diǎn)的整理,后續(xù)也會(huì)整理到自己的 JavaScript知識(shí)庫(kù)——《Cute-JavaScript》 網(wǎng)站中。

另外,請(qǐng)讀者們注意,這篇文章是知識(shí)點(diǎn)的整理,方便復(fù)習(xí),所以不會(huì)介紹太詳細(xì),因?yàn)楫吘乖瓡?shū)寫(xiě)得非常棒,剛?cè)腴T(mén)的朋友,我還是建議看下原書(shū)。

然后可以看看這篇文章,來(lái)回顧重要知識(shí)點(diǎn)。

《JavaScript 正則表達(dá)式迷你書(shū)》

《Cute-JavaScript》

目錄

一、正則表達(dá)式字符匹配

二、正則表達(dá)式位置匹配

三、正則表達(dá)式括號(hào)的使用

四、正則表達(dá)式回溯法原理

五、正則表達(dá)式的拆分

六、正則表達(dá)式的構(gòu)建

七、正則表達(dá)式編程

文章推薦(補(bǔ)充中)

老姚 —— JS正則表達(dá)式完整教程

常見(jiàn)的正則表達(dá)式可視化描述

工具推薦

Regulex*%3F%24)

Rubular

一、正則表達(dá)式字符匹配

原書(shū)這么一句話(huà),特別棒:正則表達(dá)式是匹配模式,要么匹配字符,要么匹配位置,要記住。

1. 兩種模糊匹配

正則表達(dá)式的強(qiáng)大在于它的模糊匹配,這里介紹兩個(gè)方向上的“模糊”:橫向模糊和縱向模糊。

橫向模糊匹配

即一個(gè)正則可匹配的字符串長(zhǎng)度不固定,可以是多種情況。

/ab{2,5}c/ 表示匹配: 第一個(gè)字符是 "a" ,然后是 2 - 5 個(gè)字符 "b" ,最后是字符 "c"

let r = /ab{2,5}c/g;
let s = "abc abbc abbbc abbbbbbc";
s.match(r); // ["abbc", "abbbc"]

縱向模糊匹配

即一個(gè)正則可匹配某個(gè)不確定的字符,可以有多種可能。

/[abc]/ 表示匹配 "a", "b", "c" 中任意一個(gè)。

let r = /a[123]b/g;
let s = "a0b a1b a4b";
s.match(r); // ["a1b"]
2. 字符組

范圍表示法

可以指定字符范圍,比如 [1234abcdUVWXYZ] 就可以表示成 [1-4a-dU-Z] ,使用 - 來(lái)進(jìn)行縮寫(xiě)。

如果要匹配 "a", "-", "z" 中任意一個(gè)字符,可以這么寫(xiě): [-az][a-z][az-] 。

排除字符組

即需要排除某些字符時(shí)使用,通過(guò)在字符組第一個(gè)使用 ^ 來(lái)表示取反,如 [^abc] 就表示匹配除了 "a", "b", "c" 的任意一個(gè)字符。

常見(jiàn)簡(jiǎn)寫(xiě)形式

字符組 具體含義
d 表示 [0-9],表示一位數(shù)字。
D 表示 [^0-9],表示除數(shù)字外的任意字符。
w 表示 [0-9a-zA-Z_],表示數(shù)字、大小寫(xiě)字母和下劃線(xiàn)。
W 表示 [^0-9a-zA-Z_],表示非單詞字符。
s 表示 [ v f],表示空白符,包含空格、水平制表符、垂直制表符、換行符、回車(chē)符、換頁(yè)符。
S 表示 [^ v f],表示非空白字符。
. 表示 [^ u2028u2029] 。通配符,表示幾乎任意字符。換行符、回車(chē)符、行分隔符和段分隔符除外。

然后表示任意字符,就可以使用 [dD]、[wW]、[sS][^] 任意一個(gè)。

3. 量詞

量詞也稱(chēng)重復(fù),常用簡(jiǎn)寫(xiě)如下:

量詞 具體含義
{m,} 表示至少出現(xiàn) m 次。
{m} 等價(jià)于 {m, m} ,表示出現(xiàn) m 次。
? 等價(jià)于 {0, 1} ,表示出現(xiàn)或不出現(xiàn)。
+ 等價(jià)于 {1, } ,表示至少出現(xiàn)1次。
* 等價(jià)于 {0, } ,表示出現(xiàn)任意次,也有可能不出現(xiàn)。

貪婪匹配和惰性匹配

在正則 /d{2,4}/ ,表示數(shù)字連續(xù)出現(xiàn) 2 - 4 次,可以匹配到 2 位、 3 位、4 位連續(xù)數(shù)字。

但是在 貪婪匹配/d{2,4}/g ,會(huì)盡可能多匹配,如超過(guò) 4 個(gè),就只匹配 4 個(gè),如有 3 個(gè),就匹配 3 位。

而在 惰性匹配/d{2,4}?/g ,會(huì) 盡可能少 匹配,如超過(guò) 2 個(gè),就只匹配 2 個(gè),不會(huì)繼續(xù)匹配下去。

let r1 = /d{2,4}/g;
let r2 = /d{2,4}?/g;
let s  = "123 1234 12345"; 
s.match(r1); // ["123", "1234", "1234"]
s.match(r2); // ["12", "12", "34", "12", "34"]
惰性量詞 貪婪量詞
{m,m}? {m,m}
{m,}? {m,}
?? ?
+? +
*? *
4. 多選分支

即提供多個(gè)子匹配模式任選一個(gè),使用 |(管道符)分隔,由于分支結(jié)構(gòu)也是惰性,即匹配上一個(gè)后,就不會(huì)繼續(xù)匹配后續(xù)的。

格式如:(r1|r2|r3),我們就可以使用 /leo|pingan/ 來(lái)匹配 "leo""pingan"

let r = /leo|pingan/g;
let s = "leo cool,pingan good.";
s.match(r);// ["leo", "pingan"]

// 多選分支的惰性表現(xiàn)
let r1 = /leo|leooo/g;
let r2 = /leooo|leo/g;
let s  = "leooo";
s.match(r1);// ["leo"]
s.match(r2);// ["leooo"]
5. 案例分析

匹配字符,無(wú)非就是字符組、量詞和分支結(jié)構(gòu)的組合使用。

十六進(jìn)制顏色值匹配

let r = /#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}/g;
let s = "#ffaacc #Ff00DD #fFF #01d #9Gd";
s.match(r); // ["#ffaacc", "#Ff00DD", "#fFF", "#01d"]

時(shí)間和日期匹配

// 時(shí)間 12:23 或 01:09
let r = /^([01][0-9]|[2][0-3]):[0-5][0-9]$/;  
r.test("23:25"); // true
r.test("03:05"); // true

// 時(shí)間 12:23 或 1:9
let r = /^(0?[0-9]|1[0-9]|[2][0-3]):(0?[0-9]|[1-5][0-9])$/;  
r.test("23:25"); // true
r.test("03:05"); // true
r.test("3:5");   // true

// 日期 yyyy-mm-dd
let r = /^[0-9]{4}-(0[1-9]|[1][0-2])-(0[1-9]|[12][0-9]|3[01])$/;
r.test("2019-09-19"); // true
r.test("2019-09-32"); // false

Windows操作系統(tǒng)文件路徑匹配

盤(pán)符使用 [a-zA-Z]: ,這里需要注意 字符需要轉(zhuǎn)義,并且盤(pán)符不區(qū)分大小寫(xiě);
文件名或文件夾名,不能包含特殊字符,使用 [^:*<>|"? /] 表示合法字符;
并且至少有一個(gè)字符,還有可以出現(xiàn)任意次,就可以使用 ([^:*<>|"? /]+)* 匹配任意個(gè) 文件夾
還有路徑最后一部分可以是 文件夾 ,即沒(méi)有 于是表示成 ([^:*<>|"? /]+)?。

let r = /^[a-zA-Z]:([^:*<>|"?
/]+)*([^:*<>|"?
/]+)?$/;
r.test("C:documentleoa.png"); // true
r.test("C:documentleo");      // true
r.test("C:document");             // true
r.test("C:");                     // true

id匹配

如提取

中的 id="leo"

let r1 = /id=".*"/;    // tips1
let r2 = /id=".*?"/;   // tips2
let r3 = /id="[^"]*"/; // tips3

let s  = "
"; s.match(r1)[0]; // id="leo" class="good" s.match(r2)[0]; // id="leo" s.match(r3)[0]; // id="leo"

tips1:由于 . 匹配雙引號(hào),且 * 貪婪,就會(huì)持續(xù)匹配到最后一個(gè)雙引號(hào)結(jié)束。
tips2:使用惰性匹配,但效率低,有回溯問(wèn)題。
tips3:最終優(yōu)化。

二、正則表達(dá)式位置匹配

位置匹配,就是要匹配每個(gè)字符兩邊的位置。

ES5 中有6個(gè)位置: ^,$,,B,(?=p)(?!p)。

另外把位置理解成空字符是非常有用的:

/^^hello$$/.test("hello");  // true
/^^^hello$$/.test("hello"); // true
1. ^ 和 $

^ 匹配開(kāi)頭,多行中匹配行開(kāi)頭。
$ 匹配結(jié)尾,多行中匹配行結(jié)尾。

"hello".replace(/^|$/g, "#"); // "#hello#"
"hello
leo
haha".replace(/^|$/gm, "#");
/*
#hello#
#leo#
#haha#
*/

多行匹配模式使用 m 修飾符。

2. B

 匹配單詞邊界,即 wW 之間的位置,包括 w^ 之間的位置,和 w$ 之間的位置。
B 相反,即非單詞邊界,匹配中除去 ,剩下的都是 B 的。
也就是 ww、 WW、^W,W$ 之間的位置。。

"[HI] Leo_1.mp4".replace(//g,"#");
// "[#HI#] #Leo_1#.#mp4#"

"[HI] Leo_1.mp4".replace(/B/g,"#");
// "#[H#I]# L#e#o#_#1.m#p#4"
3. (?=p)(?!p)

p 為一個(gè)子模式,即 (?=p) 匹配前面是 p 的位置,而 (?!p) 則匹配前面不是 p 的位置。

"hello".replace(/(?=l)/g, "#");
// "he#l#lo"

"hello".replace(/(?!l)/g, "#");
// "#h#ell#o#"
4. 相關(guān)案例

匹配數(shù)字千位分隔符

// 匹配最后一個(gè)逗號(hào)
"12345678".replace(/(?=d{3}$)/g, ","); // "12345,678"

// 匹配所有逗號(hào)
"12345678".replace(/(?=(d{3})+$)/g, ","); // "12,345,678"

// 匹配其余
"123456789".replace(/(?=(d{3})+$)/g, ","); // ",123,456,789"

// 修改
"123456789".replace(/(?!^)(?=(d{3})+$)/g, ","); // "12,345,678"

// 其他形式
"12345678 123456789".replace(/(?!)(?=(d{3})+)/g, ","); 
// (?!) 等于 B ,要求當(dāng)前是一個(gè)位置,但不是  前面的位置
// "12,345,678 123,456,789"

數(shù)據(jù)格式化

let num = 1888;
num.toFixed(2).replace(/B(?=(d{3})+)/g, ",").replace(/^/,"$$ ");
// "$ 1,888.00"

驗(yàn)證密碼

// 密碼長(zhǎng)度 6-12 位數(shù)字或字母
let r = /^[0-9A-Za-z]{6,12}$/;

// 必須包含一個(gè)字符(數(shù)字) + 密碼長(zhǎng)度 6-12 位數(shù)字或字母
let r = /(?=.*[0-9])^[0-9A-Za-z]{6,12}$/;

// 必須包含兩個(gè)個(gè)字符(數(shù)字和小寫(xiě)字符)  + 密碼長(zhǎng)度 6-12 位數(shù)字或字母
let r = /(?=.*[0-9])(?=.*[a-z])^[0-9A-Za-z]{6,12}$/;

r.test("aa1234566"); // true
r.test("1234566");   // false


// 密碼長(zhǎng)度 6-12 位數(shù)字或字母 
// 即 不能全是數(shù)字 或 不能全是大寫(xiě)或小寫(xiě)字母
let r = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;
三、正則表達(dá)式括號(hào)的使用

簡(jiǎn)單理解:括號(hào)提供了分組,便于我們使用它。

通常有兩種引用情況:在JS代碼中引入,和在正則表達(dá)式中引入。

分組和分支結(jié)構(gòu),主要是強(qiáng)調(diào)括號(hào)內(nèi)是一個(gè)整體,即提供子表達(dá)式。

分組如 /(ab)+/g 匹配連續(xù)出現(xiàn)的 ab 。

分支結(jié)構(gòu)如 /(a|b)+/g 匹配出現(xiàn)的 ab 表達(dá)式。

1.分組引用

如在日期匹配的時(shí)候,就可以這么改造:

// 原來(lái)
let r = /d{4}-d{2}-d{2}/;

// 現(xiàn)在
let r = /(d{4})-(d{2})-(d{2})/;

提取數(shù)據(jù)

"2019-03-14".match(r);
r.exec("2019-03-14");
// ["2019-03-14", "2019", "03", "14", index: 0, input: "2019-03-14"]

RegExp.$1; // "2019"
RegExp.$2; // "03"
RegExp.$3; // "14"

替換

yyyy-mm-dd 轉(zhuǎn)成 mm/dd/yyyy。

"2019-03-14".replace(r, "$2/$3/$1");
// 等價(jià)于
"2019-03-14".replace(r, function(){
    return RegExp.$2 + "/" + RegExp.$3 + "/" + RegExp.$1;
});
2. 反向引用

使用 表示第 n 個(gè)分組,比如 1 表示第 1 個(gè)分組:

let r = /d{4}(-|/|.)d{2}1d{2}/;
r.test("2019-03-15");
r.test("2019/03/15");
r.test("2019.03.15");
r.test("2019-03/15");

多個(gè)括號(hào)嵌套

按照開(kāi)括號(hào)的順序:

let r = /^((d)(d(d)))1234$/;
let s = "1231231233";
r.test(s);
console.log([RegExp.$1,RegExp.$2,RegExp.$3,RegExp.$4]);
// ["123", "1", "23", "3"]

特殊情況

10 表示的是第 10 個(gè)分組,若要匹配 0 時(shí),使用 (?:1)01(?:0)

let r = /(1)(2)(3)(4)(5)(6)(7)(8)(9)(#) 10+/;
let s = "123456789# #####";
r.test(s);  // true

當(dāng)引用不存在的分組

如匹配 2 是前面不存在,則匹配 2 本身,即對(duì) 2 的轉(zhuǎn)義,不同瀏覽器可能不同:

let r = /1234/;
r.test("1234");  // true
"1234".split("");// ["", "", "", ""]

分組后面有量詞

當(dāng)分組后面有量詞的話(huà),則捕獲的是最后一次的匹配:

"12345".match(/(d)+/); // ["12345", "5", index: 0, input: "12345"]

/(d)+ 1/.test("12345 1"); // false
/(d)+ 1/.test("12345 5"); // true
3. 相關(guān)案例

這里只寫(xiě)出核心代碼。

模擬字符串 trim 方法

// 1 匹配首尾空白符,替換成空字符
"  aaa   ".replace(/^s+|s+$/g, "");      // "aaa"

// 2 匹配整個(gè)字符串,再用引用提取對(duì)應(yīng)數(shù)據(jù)
"  aaa   ".replace(/^s*(.*?)s*$/g, "$1");// "aaa"

每個(gè)單詞首字母大寫(xiě)

"hi leo hi boy!".toLowerCase().replace(
    /(?:^|s)w/g, 
    c => c.toUpperCase()
);
// "Hi Leo Hi Boy!"

駝峰化 和 中劃線(xiàn)化

"-leo-and-pingan".replace(/[-_s]+(.)?/g,
    (match, c) => c ? c.toUpperCase() : ""
);
// "LeoAndPingan"

"LeoAndPingan".replace(/([A-Z])/g, "-$1").replace(
    /[-_s]+g/,"-"
).toLowerCase();
// "-leo-and-pingan"

匹配成對(duì)HTML標(biāo)簽

匹配成對(duì)標(biāo)簽

leo

,而不匹配不成對(duì)標(biāo)簽

leo

。

let r = /<([^>]+)>[dD]*/;
r.test("

leo leo leo

"); // true r.test("leo leo leo"); // true r.test("

leo leo leo

"); // false
四、正則表達(dá)式回溯法原理

概念理解起來(lái)比較容易。
比如用 /ab{1,3}c/ 去匹配下面兩個(gè)字符串。

當(dāng)匹配 abbbc,按順序匹配,到了第 3 個(gè) b 后,直接匹配 c,這樣就沒(méi)有回溯。

當(dāng)匹配 abbc,按順序匹配,到了第 2 個(gè) b 后,由于規(guī)則是 b{1,3} ,則會(huì)繼續(xù)往下匹配,然后發(fā)現(xiàn)下一位是 c,于是回退到前一個(gè)位置,重新匹配,這就是回溯。

另外像 /".*"/ 來(lái)匹配 "abc"de 的話(huà),就會(huì)有三個(gè)回溯情況,為了減少不必要的回溯,我們可以把正則修改為 /"[^"]*"/

介紹

回溯法,也稱(chēng)試探法,本質(zhì)上是深度優(yōu)先探索算法,基本思路是:匹配過(guò)程中后退到之前某一步重新探索的過(guò)程。

1. 常見(jiàn)的回溯形式

貪婪量詞

多個(gè)貪婪量詞挨著存在,并相互沖突時(shí),會(huì)看匹配順序,深度優(yōu)先搜索:

"12345".match(/(d{1,3})(d{1,3})/);
// ?["12345", "123", "45", index: 0, input: "12345"]

惰性量詞

有時(shí)候會(huì)因?yàn)榛厮?,?dǎo)致實(shí)際惰性量詞匹配到的不是最少的數(shù)量:

"12345".match(/(d{1,3}?)(d{1,3})/);
// 沒(méi)有回溯的情況?["1234", "1", "234", index: 0, input: "12345"]

"12345".match(/^d{1,3}?d{1,3}$/);
// 有回溯的情況?["12345", index: 0, input: "12345"]

分支結(jié)構(gòu)

分支機(jī)構(gòu),如果一個(gè)分支整體不匹配,會(huì)繼續(xù)嘗試剩下分支,也可以看成一種回溯。

"candy".match(/can|candy/); // ["can", index: 0, input: "candy"]

"candy".match(/^(?:can|candy)$/); // ["candy", index: 0, input: "candy"]
2. 本章小結(jié)

簡(jiǎn)單總結(jié):一個(gè)個(gè)嘗試,直到,要么后退某一步整體匹配成功,要么最后試完發(fā)現(xiàn)整體不匹配。

貪婪量詞:買(mǎi)衣服砍價(jià),價(jià)格高了,便宜點(diǎn),再便宜點(diǎn)。

懶惰量詞:賣(mài)衣服加價(jià),價(jià)格低了,多給點(diǎn),再多給點(diǎn)。

分支結(jié)構(gòu):貨比三家,一家不行換一家,不行再換。

五、正則表達(dá)式的拆分

拆分正則代碼塊,是理解正則的關(guān)鍵。

在 JavaScrip 正則表達(dá)式有以下結(jié)構(gòu):

字面量: 匹配一個(gè)具體字符,如 a 匹配字符 a。

字符組: 匹配一個(gè)有多種可能性的字符,如 [0-9] 匹配任意一個(gè)數(shù)字。

量詞: 匹配一個(gè)連續(xù)出現(xiàn)的字符,如 a{1,3} 匹配連續(xù)最多出現(xiàn) 3 次的a字符。

錨: 匹配一個(gè)位置,如 ^ 匹配字符串的開(kāi)頭。

分組: 匹配一個(gè)整體,如 (ab) 匹配 ab 兩個(gè)字符連續(xù)出現(xiàn)。

分支: 匹配一個(gè)或多個(gè)表達(dá)式,如 ab|bc 匹配 abbc 字符。

另外還有以下操作符:

優(yōu)先級(jí) 操作符描述 操作符
1 轉(zhuǎn)義符
2 括號(hào)和方括號(hào) (...)/(?:...)/(?=...)/(?!...)/[...]
3 量詞限定符 {m}/{m,n}/{m,}/?/*/+
4 位置和序列 ^/$/元字符/一般字符
5 管道符 ` `

Tips:優(yōu)先級(jí)從上到下,由高到低。

1. 注意要點(diǎn)

匹配字符串整體

不能寫(xiě)成 /^abc|bcd$/ ,而是要寫(xiě)成 /^(abc|bcd)$/。

量詞連綴問(wèn)題

需要匹配:每個(gè)字符是 a/b/c 中其中一個(gè),并且字符串長(zhǎng)度是 3 的倍數(shù):

不能寫(xiě)成 /^[abc]{3}+$/ ,而是要寫(xiě)成 /([abc]{3})+/。

元字符轉(zhuǎn)義問(wèn)題

元字符就是正則中的特殊字符,當(dāng)匹配元字符就需要轉(zhuǎn)義,如:

^、$、.、*+、?|、、/、()[、]、{、}=!、:- 。

// "[abc]"  => /[abc]/ 或者 /[abc]/ 
// "{1,3}"  => /{1}/ 或者 /{1}/ 因?yàn)椴粯?gòu)成字符組
2. 案例分析

身份證號(hào)碼

/^(d{15}|d{17})[dxX]$/.test("390999199999999999");// true

IPV4地址

需要好好分析:

let r = /^((0{0,2}d|0?d{2}|1d{2}|2[0-4]d|25[0-5]).){3}(0{0,2}d|0?d{2}|1d{2}|2[0-4]d|25[0-5])$/
六、正則表達(dá)式的構(gòu)建

正則的構(gòu)建需要考慮以下幾點(diǎn)的平衡:

匹配預(yù)期的字符串

不匹配非預(yù)期的字符串

可讀性和可維護(hù)性

效率

我們還需要考慮這么幾個(gè)問(wèn)題:

是否需要使用正則

如能使用其他 API 簡(jiǎn)單快速解決問(wèn)題就不需要使用正則:

"2019-03-16".match(/^(d{4})-(d{2})-(d{2})/); // 間接獲取?["2019", "03", "16"]
"2019-03-16".split("-"); // ?["2019", "03", "16"]

"?id=leo".search(/?/); // 0
"?id=leo".indexOf("?"); // 0

"JavaScript".match(/.{4}(.+)/)[1];  // "Script"
"JavaScript".substring(4);          // "Script"

是否需要使用復(fù)雜正則

/(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/

將這個(gè)正則拆分成多個(gè)小塊,如下:

var regex1 = /^[0-9A-Za-z]{6,12}$/;
var regex2 = /^[0-9]{6,12}$/;
var regex3 = /^[A-Z]{6,12}$/;
var regex4 = /^[a-z]{6,12}$/;
function checkPassword (string) {
    if (!regex1.test(string)) return false;
    if (regex2.test(string)) return false;
    if (regex3.test(string)) return false;
    if (regex4.test(string)) return false;
    return true;
}
1. 準(zhǔn)確性

即需要匹配到預(yù)期目標(biāo),且不匹配非預(yù)期的目標(biāo)。

匹配固定電話(huà)

如需要匹配下面固定電話(huà)號(hào)碼,可以分別寫(xiě)出對(duì)應(yīng)正則:

055188888888     => /^0d{2,3}[1-9]d{6,7}$/
0551-88888888    => /^0d{2,3}-[1-9]d{6,7}$/
(0551)88888888   => /^0d{2,3}-[1-9]d{6,7}$/

然后合并:

let r = /^0d{2,3}[1-9]d{6,7}$|^0d{2,3}-[1-9]d{6,7}$|^(0d{2,3})[1-9]d{6,7}$/

然后提取公共部分:

let r = /^(0d{2,3}|0d{2,3}-|(0d{2,3}))[1-9]d{6,7}$/

再優(yōu)化:

let r = /^(0d{2,3}-?|(0d{2,3}))[1-9]d{6,7}$/

匹配浮點(diǎn)數(shù)

先確定,符號(hào)部分([+-])、整數(shù)部分(d+)和小數(shù)部分(.d+)。

1.23、+1.23、-1.23  => /^[+-]?d+.d+$/
10、+10、-10        => /^[+-]?d+$/
.2、+.2、-.2        => /^[+-]?.d+$/

整理后:

let r = /^[+-]?(d+.d+|d+|.d+)$/;

// 考慮不匹配 +.2 或 -.2
let r = /^([+-])?(d+.d+|d+|.d+)$/;

// 考慮不匹配 012 這類(lèi) 0 開(kāi)頭的整數(shù)
let r = /^[+-]?(d+)?(.)?d+$/;
2. 效率

正則表達(dá)式運(yùn)行過(guò)程:

編譯

設(shè)定起始位置

嘗試匹配

若匹配失敗則返回前一步重新匹配

返回匹配成功失敗的結(jié)果

我們常常優(yōu)化對(duì) 3 和 4 步進(jìn)行優(yōu)化:

使用具體字符組替代通配符,消除回溯

/"[^"]*"/ 代替 /".*?"/。

使用非捕獲型分組

當(dāng)不需要使用分組引用和反向引用時(shí),此時(shí)可以使用非捕獲分組。

/^[-]?(?:d.d+|d+|.d+)$/ 代替 /^[-]?(d.d+|d+|.d+)$/。

獨(dú)立出確定字符

加快判斷是否匹配失敗,進(jìn)而加快移位的速度。

/aa*/ 代替 /a+/。

提取分支公共部分

減少匹配過(guò)程中可消除的重復(fù)。

/^(?:abc|def)/ 代替 /^abc|^def/。

減少分支的數(shù)量,縮小它們的范圍

/rea?d/ 代替 /red|read/。

七、正則表達(dá)式編程

這里要掌握正則表達(dá)式怎么用,通常會(huì)有這么四個(gè)操作:

驗(yàn)證

切分

提取

替換

1. 四種操作

驗(yàn)證

匹配本質(zhì)上是查找,我們可以借助相關(guān)API操作:

// 檢查字符串是否包含數(shù)字
let r = /d/, s = "abc123";
!!s.search(r); // true
r.test(s);     // true
!!s.match(r);  // true
!!r.exec(s);   // true

切分

"leo,pingan".split(/,/); // ["leo", "pingan"]

let r = /D/, s = "2019-03-16";
s.split(r);   //?["2019", "03", "16"]
s.split(r);   //?["2019", "03", "16"]
s.split(r);   //?["2019", "03", "16"]

提取

// 提取日期年月日
let r = /^(d{4})D(d{2})D(d{2})$/;
let s = "2019-03-16";

s.match(r); // ["2019-03-16", "2019", "03", "16", index: 0, input: "2019-03-16"]
r.exec(s);  // ["2019-03-16", "2019", "03", "16", index: 0, input: "2019-03-16"]
r.test(s);  // RegExp.$1 => "2019" RegExp.$2 => "03" RegExp.$3 => "16"
s.search(r);// RegExp.$1 => "2019" RegExp.$2 => "03" RegExp.$3 => "16"

替換

// yyyy-mm-dd 替換成 yyyy/mm/dd
"2019-03-16".replace(/-/g, "/");
2. 相關(guān)API注意

searchmatch 參數(shù)問(wèn)題

這兩個(gè)方法會(huì)把字符串轉(zhuǎn)換成正則,所以要加轉(zhuǎn)義

let s = "2019.03.16";
s.search(".");    // 0
s.search(".");  // 4
s.search(/./);  // 4
s.match(".");     // ["2", index: 0, input: "2019.03.16"]
s.match(".");   // [".", index: 4, input: "2019.03.16"]
s.match(/./);   // [".", index: 4, input: "2019.03.16"]

// 其他不用轉(zhuǎn)義
s.split(".");
s.replace(".", "/");

match 返回結(jié)果的格式問(wèn)題

match 參數(shù)有 g 會(huì)返回所有匹配的內(nèi)容,沒(méi)有 g 則返回標(biāo)準(zhǔn)匹配格式:

let s = "2019.03.16";
s.match(/(d+)/);  // ["2019", "2019", index: 0, input: "2019.03.16"]
s.match(/(d+)/g); // ["2019", "03", "16"]

test 整體匹配時(shí)需要使用 ^$

/123/.test("a123b");    // true
/^123$/.test("a123b");  // false
/^123$/.test("123");    // true

split 的注意點(diǎn)

split 第二個(gè)參數(shù)是 結(jié)果數(shù)組的最大長(zhǎng)度

"leo,pingan,pingan8787".split(/,/, 2); // ["leo", "pingan"]

使用正則分組,會(huì)包含分隔符:

"leo,pingan,pingan8787".split(/(,)/); // ["leo", ",", "pingan", ",", "pingan8787"]

修飾符

修飾符 描述
g 全局匹配,即找到所有匹配的,單詞是 global。
i 忽略字母大小寫(xiě),單詞是 ingoreCase。
m 多行匹配,只影響 ^$,二者變成行的概念,即行開(kāi)頭和行結(jié)尾。單詞是 multiline

文章到這結(jié)束,感謝閱讀,也感謝老姚大佬的這本書(shū)

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 https://github.com/pingan8787...
ES小冊(cè) js.pingan8787.com
微信公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102610.html

相關(guān)文章

  • 正則達(dá)式

    摘要:本文內(nèi)容共正則表達(dá)式火拼系列正則表達(dá)式回溯法原理學(xué)習(xí)正則表達(dá)式,是需要懂點(diǎn)兒匹配原理的。正則表達(dá)式迷你書(shū)問(wèn)世了讓幫你生成和解析參數(shù)字符串最全正則表達(dá)式總結(jié)驗(yàn)證號(hào)手機(jī)號(hào)中文郵編身份證地址等是正則表達(dá)式的縮寫(xiě),作用是對(duì)字符串執(zhí)行模式匹配。 JS 的正則表達(dá)式 正則表達(dá)式 一種幾乎可以在所有的程序設(shè)計(jì)語(yǔ)言里和所有的計(jì)算機(jī)平臺(tái)上使用的文字處理工具。它可以用來(lái)查找特定的信息(搜索),也可以用來(lái)查...

    bang590 評(píng)論0 收藏0
  • JavaScript正則達(dá)式迷你書(shū)-筆記

    摘要:比如正則表示匹配這樣一個(gè)字符串第一個(gè)字符是,接下來(lái)是到個(gè)字符,最后是字符。其實(shí)現(xiàn)的方式是使用字符組。具體形式如下,其中和是子模式,用管道符分隔,表示其中任何之一。 貪婪模式: 在使用修飾匹配次數(shù)的特殊符號(hào)時(shí),有幾種表示方法可以使同一個(gè)表達(dá)式能夠匹配不同的次數(shù),比如:{m,n}, {m,}, ?, *, +,具體匹配的次數(shù)隨被匹配的字符串而定。這種重復(fù)匹配不定次數(shù)的表達(dá)式在匹配過(guò)程中,總...

    widuu 評(píng)論0 收藏0
  • 正則達(dá)式迷你書(shū)-筆記

    摘要:使用看完你就會(huì)正則表達(dá)式了四種操作驗(yàn)證切分提取替換第一章正則表達(dá)式字符匹配攻略正則表達(dá)式是匹配模式,要么匹配字符,要么匹配位置至少,至多匹配中的任一個(gè)字符范圍表示法如果要匹配則要么要么要么通配符,表示幾乎任意 API 使用 String#search String#split String#match String#replace RegExp#test Reg...

    IamDLY 評(píng)論0 收藏0
  • 前端學(xué)習(xí)資源

    摘要:提供了完整的環(huán)境,并且支持自定義域名指向,動(dòng)態(tài)計(jì)算資源調(diào)整,可以完成各種應(yīng)用的開(kāi)發(fā)編譯與部署。 react 新特性 react16 Context 算法相關(guān) 圖解排序算法(二)之希爾排序 微信小程序 微信小程序組件化的解決方案移動(dòng)端尺寸基本知識(shí) 瀏覽器 前端必讀:瀏覽器內(nèi)部工作原理瀏覽器緩存原理解讀瀏覽器加載css和js及dom解析之間的關(guān)系瀏覽器緩存 CSS學(xué)習(xí) 移動(dòng)web開(kāi)發(fā)布局入...

    zhisheng 評(píng)論0 收藏0
  • javascript正則迷你書(shū)-筆記

    showImg(https://segmentfault.com/img/bVbfGSV?w=719&h=718); showImg(https://segmentfault.com/img/bVbfGTc?w=801&h=552); showImg(https://segmentfault.com/img/bVbfGTq?w=1017&h=501);

    LinkedME2016 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<