壹 ❀ 引html
花了差很少半個月的晚上時間,正則入門學習也步入尾聲了,固然正則的學習還將繼續。不得不說學習成效很是明顯,已能看懂大部分正則以及寫出不太複雜的正則,好比幫組長寫正則驗證文件路徑正確性,再如進產品頁根據頁面地址獲取產品id:git
let pathname = '/webtoprint/dynamicsize-gamebox-2033986.html'; let productId = pathname.match(/\-(\d+)\./)[1]; //2033986
雖然正則都不難,可是相比以前使用split各類切切切真的要舒服的多,想到這一點就開心。因此若是有緣的你看到這篇做爲結束的文章,仍是很是推薦靜下心花點閒餘時間學習正則。github
那麼在最終章,咱們將正則與API結合起來,真正把正則用起來,畢竟學了不用總會忘,忘了再學就鉅虧。說在前面,正則學習系列文章均爲我閱讀 老姚《JavaScript正則迷你書》的讀書筆記,文中全部正則圖解均使用regulex製做。那麼本文開始!web
貳 ❀ 正則的四種操做數組
咱們知道正則是一種匹配模式,要麼匹配字符,要麼匹配位置,正則的核心用處就是在於匹配咱們預期的東西。那麼拿到了想要的東西能作什麼?其實無非就是用於驗證,切分,提取以及替換。好比文章開頭匹配產品id就是提取咱們想要的東西,再如千位分隔符就是將數字替換成咱們想要的樣子,其實也不難理解,咱們來細說這四種操做。函數
1.驗證學習
談到驗證首先想到的就是表單驗證,使用正則驗證用戶輸入字段是否符合規範,好比驗證數字密碼長度是否爲六位,最經常使用的就是使用test方法:spa
var regex = /^\d{6}$/; regex.test(123456); //true regex.test(12345); //false regex.test(1234567); //false
除了字符的完整比較驗證,有時候咱們也須要驗證字符中是否包含某個特定字符,這種狀況下除了test,咱們能用match,search,exec這三個方法來作,好比驗證字符中是否包含 ❀ :3d
可使用 test 方法:code
var regex = /❀/; regex.test('123❀'); //true regex.test('a❀b'); //false regex.test('echo'); //false
使用match方法,此時返回並不是布爾值,而是匹配結果,若要判斷有沒有隻需對比返回值是否等於null便可:
var regex = /❀/; '123❀'.match(regex); //["❀", index: 3, input: "123❀", groups: undefined] 'a❀b'.match(regex); //["❀", index: 1, input: "a❀b", groups: undefined] 'echo'.match(regex); //null
使用search方法,此時返回第一個符合條件字符的索引,若沒找到返回-1,因此判斷有沒有對比是否等於-1便可:
var regex = /❀/; '❀123❀'.search(regex); //0 'a❀b'.search(regex); //1 'echo'.search(regex); //-1
使用exec方法,此方法結果與match相似,判斷有沒有看是否爲null便可:
var regex = /❀/; regex.exec('❀123❀'); //["❀", index: 0, input: "❀123❀", groups: undefined] regex.exec('a❀b'); //["❀", index: 1, input: "a❀b", groups: undefined] regex.exec('echo'); //null
固然若是真的是判斷有沒有某個字符的需求,其實用 indexOf 就能夠了,這裏也只是列舉這些方法的做用。
2.切分
說到切分天然想到字符串切分的split方法,好比:
var str = 'hello echo'; var a = str.split(" "); console.log(a, str); //["hello", "echo"] "hello echo"
split方法返回一個切割後的數組,它並不會修改原字符串。其實split接受參數除了字符意外,它還能接受一個正則做爲切分條件,好比上面的例子咱們也能夠寫成:
var str = 'hello echo'; var a = str.split(/\s/); console.log(a, str); //["hello", "echo"] "hello echo"
3.提取
正如文章開頭提取產品id的例子同樣,正則提取操做很是使用,而提取就依賴於正則分組存儲的特性,因此分組記得必定不能使用非捕獲型括號,看個簡單的例子:
var regex = /(\d{4})\/(\d{2})\/(\d{2})/; var result = regex.exec('2019/12/28'); //["2019/12/28", "2019", "12", "28", index: 0, input: "2019/12/28", groups: undefined] console.log(result[1]); //2019 console.log(result[2]); //12 console.log(result[3]); //28 // 或直接經過RegExp對象訪問 console.log(RegExp.$1); //2019 console.log(RegExp.$2); //12 console.log(RegExp.$3); //28
4.替換
替換必須依賴字符串replace方法,好比將yyyy/mm/dd修改成yyyy-mm-dd:
var str = 'yyyy/mm/dd'; var result = str.replace(/\//g, '-'); console.log(result, str); //yyyy-mm-dd yyyy/mm/dd
注意replace返回替換後的字符,並不會修改原字符串。
叄 ❀ 正則相關的API使用注意
整合上文四種正則操做能夠發現,正則使用的API一共就六個,其中字符串方法四個,正則方法兩個:
字符串方法split:負責字符串切分,可以使用正則做爲切分條件,返回切分後的數組,不修改原字符串。
字符串方法search:根據正則查找並返回第一個符合條件的字符索引,注意是第一個,若是沒找到返回-1。
字符串方法match:根據正則匹配符合條件的字符,返回一個數組,若是沒找到返回null,此方法與exec相似。
字符串方法relpace:根據正則條件進行字符替換,返回替換完成的字符,不會修改源字符串。
正則方法exec:與match相似,返回一個包含符合條件字符,分組匹配字符等信息的數組,沒找到返回null。
正則方法test:驗證時經常使用,驗證字符是否有符合正則條件的字符,返回一個Boolean值,有爲true,沒有返回false。
在使用這些方法時,仍是有一些須要注意的點,這裏咱們作個整合:
1.search與match會將字符參數轉爲正則
字符串的split,replact,match,search四個方法都接受字符串或者正則做爲參數,但在使用時,match與search會將字符串參數轉爲正則:
var str = '2019.12.28'; var result1 = str.search('.'); //0 var result2 = str.match('.'); //["2", index: 0, input: "2019.12.28", groups: undefined]
在上面的例子,咱們本意是匹配第一個小數點的位置,但這兩個方法將小數點轉爲了正則,也就是通配符,很天然第一個數字2就符合條件,因此search返回了2的索引0,match返回了2。
爲了不這個問題仍是建議匹配條件直接使用正則,避免沒必要要的麻煩,像這樣:
var str = '2019.12.28'; var result1 = str.search('\\.'); //4 var result2 = str.match(/\./); //[".", index: 4, input: "2019.12.28", groups: undefined]
固然若是隻是查找某個字符有沒有,仍是推薦indexOf,不用像上面花裏胡哨。
2.match匹配受修飾符g影響
咱們在前面說字符串方法match與正則方法exec很是相似,若成功匹配都是返回一個數組,失敗返回null,而數組中包含了第一個符合條件的字符,分組捕獲字符等信息:
var str = '2019.12.28'; var result1 = str.match(/\d+/); //["2019", index: 0, input: "2019.12.28", groups: undefined] var result2 = /\d+/.exec('2019.12.28'); //["2019", index: 0, input: "2019.12.28", groups: undefined]
能夠看到不加g狀況兩個方法匹配結果徹底同樣,如今咱們加上全局匹配修飾符g再看:
var str = '2019.12.28'; var result1 = str.match(/\d+/g); //["2019", "12", "28"] var result2 = /\d+/g.exec('2019.12.28'); //["2019", index: 0, input: "2019.12.28", groups: undefined]
當match方法的正則添加了修飾符g,返回結果將只包含全部符合條件的字符,再也不包含字index等信息。而exec方法很明顯不受g影響。
3.exec使用修飾符g的妙用
上面說match方法使用了g雖然能拿到全部符合條件的字符,但不知道每次出現的索引信息,exec正好解決了這個問題。
當exec方法使用了修飾符g,exec第一次匹配從索引0開始,以後每次匹配都會從上次匹配失敗的索引位置(lastIndex)開始,直至匹配一圈後重置索引爲0,也就是開始下一輪匹配:
var str = '2019.12.28'; var regexp = /\d+/g console.log(regexp.exec('2019.12.28'), regexp.lastIndex); // ["2019", index: 0, input: "2019.12.28", groups: undefined] 4 console.log(regexp.exec('2019.12.28'), regexp.lastIndex); // ["12", index: 5, input: "2019.12.28", groups: undefined] 7 console.log(regexp.exec('2019.12.28'), regexp.lastIndex); // ["28", index: 8, input: "2019.12.28", groups: undefined] 10 console.log(regexp.exec('2019.12.28'), regexp.lastIndex); // null 0 console.log(regexp.exec('2019.12.28'), regexp.lastIndex); // ["2019", index: 0, input: "2019.12.28", groups: undefined] 4
能夠看到在走完第四次匹配後,字符串被完整匹配了一遍,此時lastIndex又被重置爲0,接下來又開始新一輪匹配。
4.test也會受修飾符g影響
前面說exec會受g影響,準確來講正則的兩個方法都受g影響,另外一個方法test也是如此,只要添加了全局修飾符g,正則每次匹配完成都會修改lastIndex,這一點與exec保持一致:
var str = '2019.12.28'; var regexp = /\d+/g console.log(regexp.test('2019.12.28'), regexp.lastIndex); // true 4 console.log(regexp.test('2019.12.28'), regexp.lastIndex); // true 7 console.log(regexp.test('2019.12.28'), regexp.lastIndex); // true 10 console.log(regexp.test('2019.12.28'), regexp.lastIndex); // false 0 console.log(regexp.test('2019.12.28'), regexp.lastIndex); //true 4
5.驗證字符總體要加^和$
這個在前面幾篇文章已經有說過,通常咱們驗證用戶輸入表單信息,都是驗證用戶輸入的完整字符是否符合規格,因此要驗證總體是否符合,必定得加^和$:
var regexp = /\d{6}/; console.log(regexp.test('1234567')); // true console.log(regexp.test('123456')); // true var regexp = /^\d{6}$/; console.log(regexp.test('1234567')); // false console.log(regexp.test('123456')); // true
好比這個例子中咱們要求密碼必須是6位數字,若是不加^和$,七位數字也包含了六位數字的狀況,因此爲true。
6.split你不知道的事
split方法咱們在前面說了它接受一個字符或者一個正則做爲切分字符的條件,並將字符按此條件切成一個數組並返回。
其實split方法還能接受第二個參數,用於限定返回數組的長度:
var str = '聽風是風 時間跳躍 行星飛行 echo'; console.log(str.split(' ', 2)); //["聽風是風", "時間跳躍"]
第二點是,若是咱們使用正則做爲切分條件,且正則使用了分組,那麼返回的數據將包含分隔符:
var str = '聽風是風 時間跳躍 行星飛行 echo'; console.log(str.split(/(\s)/)); //["聽風是風", " ", "時間跳躍", " ", "行星飛行", " ", "echo"]
7.強大的replace方法
咱們理解的replace方法第二參數就是自定義字符,最基本的用法:
var str = '聽風是風 時間跳躍 行星飛行 echo'; console.log(str.replace(/\s/g,'❀')); //聽風是風❀時間跳躍❀行星飛行❀echo
其實正則自身也提供了一部分字符,以下:
屬性 | 描述 |
$1,$2...$99 | 匹配第1-99個分組裏捕獲的文本 |
$& | 匹配到的子串文本 |
$` | 匹配到的子串的左邊文本 |
$' | 匹配到的子串的右邊文本 |
$$ | 美圓符號 |
好比將 2019/12/29 替換成 2019-12-28,能夠這麼作,這裏解釋了$1,$2含義:
var str = '2019/12/29'; console.log(str.replace(/(\d{4})\/(\d{2})\/(\d{2})/g, '$1-$2-$3')); //2019-12-29 console.log(RegExp.$1); //2019 console.log(RegExp.$2); //12 console.log(RegExp.$3); //29
咱們來經過一個例子來解釋$&,以下:
var result = "a,b,c".replace(/\w/g, "$&$&"); console.log(result);//aa,bb,cc
不少人看到這裏可能就不理解了,這是怎麼替換的?記住一點,replace具備遍歷特性,前面正則能匹配到幾回,後面的替換就會執行幾回。
第一次匹配到了a,因此此時的 $&表示 a,執行替換,a被替換成了 aa。
第二次匹配到了b,此時的$&表示 b,又執行替換,此時b又變成了bb,以此類推,經歷過三次替換因而變成了aa,bb,cc。
咱們經過一個例子來解釋 $` 和 $':
var result = "2+3=5".replace(/=/, "$`----$'"); console.log(result); //2+32+3----55
整個匹配下來只有一個 = ,因此$`表示 = 左邊的內容,也就是2+3,對應的 $'表示 = 右邊的內容,也就是5。別忘了replace是將匹配到的內容替換掉,因此 = 被替換成了 2+3----5。
說到這確定有同窗問了,要死我有多個 = 符號你咋替換,別忘了replace是會遍歷的,它會循環起來一步步替換,看個例子:
var result = "2=3=5".replace(/=/g, "$`$'"); console.log(result); //223=532=355
因爲加了修飾符g,因此這裏會匹配量詞,先說第一次,=左邊是2,右邊是3=5,組合起來就是 23=5,替換到=上去以後就是223=53=5。
匹配到了第二個 = ,注意,此時 = 左右不是以修改的字符做爲標準,而是繼續以修改前的原字符做爲切割標準,因此第二個 = 左邊是2=3,右邊是5,組合起來就是2=35,替換到 223=53=5 第二個 = 上,因而就變成了 223=532=355。
不難理解,可是懶得理解....實際開發中使用$1此類字符串較多,其它字符就隨緣了。但其實說到這裏,咱們仍是強調一點,replace會遍歷替換。
replace方法第二個參數還能夠是一個回調函數,這裏就能夠驗證咱們說的replace會遍歷的說法:
"1234 2345 3456".replace(/(\d)\d{2}(\d)/g, function (match, $1, $2, index, input) { console.log([match, $1, $2, index, input]); }); // ["1234", "1", "4", 0, "1234 2345 3456"] // ["2345", "2", "5", 5, "1234 2345 3456"] // ["3456", "3", "6", 10, "1234 2345 3456"]
8.正則構造函數
與通常對象建立可使用對象字面量,構造函數建立對象同樣,正則也能使用構造函數建立。請記住一點,能使用字面量的狀況必定使用字面量。有一種特殊狀況必須使用構造函數建立,那就是正則內容是一個變量,好比:
function regexp(param) { var regex = new RegExp(param, 'g'); console.log(regex.test('聽風是風'));//true console.log(regex.test('時間跳躍 聽風是風'));//true console.log(regex.test('時間跳躍'));//false }; regexp('聽風是風');
固然就算不是變量狀況,咱們也能用構造函數建立固定字符的正則,但本來有\的字符前你得多加一個\,因此你會發現這樣的正則特別難讀,像這樣:
var regex = new RegExp('\\d+\\.\\d+', 'g'); console.log(regex.test('3.14')); //true console.log(regex.test('.3.14')); //false //等同於 var regex = /\d+\.\d+/;
這個正則其實只是用來匹配浮點數,但\d和爲了匹配小數點使用了轉義符的\d前面都有\,因此通通再得加一個\。因此說嘛,能不用構造函數記得必定不要用。
9.正則source屬性
使用構造函數建立正則的另外一個問題就是,你不知道這是否是你想要的正則,對於這一點,咱們能夠經過source屬性查看:
var regex = new RegExp('\\d+\\.\\d+', 'g'); console.log(regex.source) //\d+\.\d+
10.構造函數屬性
在前面聊$1,$&時,我想你們必定有個問題,難道我每次都要根據替換結果來反推這些字符的意思嗎?有沒有什麼辦法直接查看呢,實際上是有的:
靜態屬性 | 描述 | 簡寫方式 |
RegExp.input | 最近一次目標字符串 | RegExp["$_"] |
RegExp.lastMatch | 最近一次匹配的文本 | RegExp["$&"] |
RegExp.lastParen | 最近一次捕獲的文本 | RegExp["$+"] |
RegExp.leftContext | 目標字符串中lastMatch以前的文本 | RegExp["$`"] |
RegExp.rightContext | 目標字符串中lastMatch以後的文本 | RegExp["$'"] |
經過靜態屬性或簡寫方式,咱們能夠直接查看這些字符到底匹配到了什麼東西:
var regex = /\w(=)/g; var string = 'a=b=c'; string.match(regex); console.log(RegExp.input); console.log(RegExp["$_"]); //a=b=c console.log(RegExp.lastMatch); console.log(RegExp["$&"]); // b= console.log(RegExp.lastParen); console.log(RegExp["$+"]); // = console.log(RegExp.leftContext); console.log(RegExp["$`"]); // a= console.log(RegExp.rightContext); console.log(RegExp["$'"]); // c
肆 ❀ 總
我讀完了這本正則表示迷你書,很開心。而後如今斷網了,博客沒法提交保存,只能用USB連接電腦苟延殘喘寫個結尾提交了。
無論怎麼說,我一路學過來也順利學完,仍是很是推薦大學花點時間好好學習正則,由於學會了以後在工做中每解決一個正則問題,那種史無前例的快感真是爽到爆炸!!!
好啦,半個月的學習順利結束,也但願你能愛上正則,一塊兒努力吧,有緣看到此文但陌生的你。