《JavaScript 正則表達式迷你書》知識點小抄本

reg

介紹

這周開始學習老姚大佬的《JavaScript 正則表達式迷你書》 , 而後習慣性的看完一遍後,整理一下知識點,便於之後本身從新複習。 git

我我的以爲:本身整理下來的資料,對於知識重現,效果不錯。 github

感謝原書做者老姚,本文無心抄襲,只是做爲本身知識點的整理,後續也會整理到本身的 JavaScript知識庫——《Cute-JavaScript》 網站中。 正則表達式

另外,請讀者們注意,這篇文章是知識點的整理,方便複習,因此不會介紹太詳細,由於畢竟原書寫得很是棒,剛入門的朋友,我仍是建議看下原書。 算法

而後能夠看看這篇文章,來回顧重要知識點。編程

目錄

  • 1、正則表達式字符匹配
  • 2、正則表達式位置匹配
  • 3、正則表達式括號的使用
  • 4、正則表達式回溯法原理
  • 5、正則表達式的拆分
  • 6、正則表達式的構建
  • 7、正則表達式編程

文章推薦(補充中)

工具推薦

1、正則表達式字符匹配

原書這麼一句話,特別棒:正則表達式是匹配模式,要麼匹配字符,要麼匹配位置,要記住。數組

1. 兩種模糊匹配

正則表達式的強大在於它的模糊匹配,這裏介紹兩個方向上的「模糊」:橫向模糊和縱向模糊。瀏覽器

  • 橫向模糊匹配

即一個正則可匹配的字符串長度不固定,能夠是多種狀況。 微信

/ab{2,5}c/ 表示匹配: 第一個字符是 "a" ,而後是 2 - 5 個字符 "b" ,最後是字符 "c"工具

let r = /ab{2,5}c/g;
let s = "abc abbc abbbc abbbbbbc";
s.match(r); // ["abbc", "abbbc"]
  • 縱向模糊匹配

即一個正則可匹配某個不肯定的字符,能夠有多種可能。 post

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

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

2. 字符組

  • 範圍表示法

能夠指定字符範圍,好比 [1234abcdUVWXYZ] 就能夠表示成 [1-4a-dU-Z] ,使用 - 來進行縮寫。

若是要匹配 "a", "-", "z" 中任意一個字符,能夠這麼寫: [-az][a\-z][az-]

  • 排除字符組

即須要排除某些字符時使用,經過在字符組第一個使用 ^ 來表示取反,如 [^abc] 就表示匹配除了 "a", "b", "c" 的任意一個字符。

  • 常見簡寫形式
字符組 具體含義
\d 表示 [0-9],表示一位數字。
\D 表示 [^0-9],表示除數字外的任意字符。
\w 表示 [0-9a-zA-Z_],表示數字、大小寫字母和下劃線。
\W 表示 [^0-9a-zA-Z_],表示非單詞字符。
\s 表示 [\t\v\n\r\f],表示空白符,包含空格、水平製表符、垂直製表符、換行符、回車符、換頁符。
\S 表示 [^\t\v\n\r\f],表示非空白字符。
. 表示 [^\n\r\u2028\u2029] 。通配符,表示幾乎任意字符。換行符、回車符、行分隔符和段分隔符除外。

而後表示任意字符,就可使用 [\d\D][\w\W][\s\S][^] 任意一個。

3. 量詞

量詞也稱重複,經常使用簡寫以下:

量詞 具體含義
{m,} 表示至少出現 m 次。
{m} 等價於 {m, m} ,表示出現 m 次。
? 等價於 {0, 1} ,表示出現或不出現。
+ 等價於 {1, } ,表示至少出現1次。
* 等價於 {0, } ,表示出現任意次,也有可能不出現。
  • 貪婪匹配和惰性匹配

在正則 /\d{2,4}/ ,表示數字連續出現 2 - 4 次,能夠匹配到 2 位、 3 位、4 位連續數字。

可是在 貪婪匹配/\d{2,4}/g ,會儘量多匹配,如超過 4 個,就只匹配 4 個,若有 3 個,就匹配 3 位。

而在 惰性匹配/\d{2,4}?/g ,會 儘量少 匹配,如超過 2 個,就只匹配 2 個,不會繼續匹配下去。

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. 多選分支

即提供多個子匹配模式任選一個,使用 |(管道符)分隔,因爲分支結構也是惰性,即匹配上一個後,就不會繼續匹配後續的。

格式如:(r1|r2|r3),咱們就可使用 /leo|pingan/ 來匹配 "leo""pingan"

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

// 多選分支的惰性表現
let r1 = /leo|leooo/g;
let r2 = /leooo|leo/g;
let s  = "leooo";
s.match(r1);// ["leo"]
s.match(r2);// ["leooo"]

5. 案例分析

匹配字符,無非就是字符組、量詞和分支結構的組合使用。

  • 十六進制顏色值匹配
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"]
  • 時間和日期匹配
// 時間 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

// 時間 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操做系統文件路徑匹配

盤符使用 [a-zA-Z]:\\ ,這裏須要注意 \ 字符須要轉義,而且盤符不區分大小寫;
文件名或文件夾名,不能包含特殊字符,使用 [^\\:*<>|"?\r\n/] 表示合法字符;
而且至少有一個字符,還有能夠出現任意次,就可使用 ([^\\:*<>|"?\r\n/]+\\)* 匹配任意個 文件夾\
還有路徑最後一部分能夠是 文件夾 ,即沒有 \ 因而表示成 ([^\\:*<>|"?\r\n/]+)?

let r = /^[a-zA-Z]:\\([^\\:*<>|"?\r\n/]+\\)*([^\\:*<>|"?\r\n/]+)?$/;
r.test("C:\\document\\leo\\a.png"); // true
r.test("C:\\document\\leo\\");      // true
r.test("C:\\document");             // true
r.test("C:\\");                     // true
  • id匹配

如提取 <div id="leo" class="good"></id> 中的 id="leo"

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

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

tips1:因爲 . 匹配雙引號,且 * 貪婪,就會持續匹配到最後一個雙引號結束。
tips2:使用惰性匹配,但效率低,有回溯問題。
tips3:最終優化。

2、正則表達式位置匹配

位置匹配,就是要匹配每一個字符兩邊的位置。

ES5 中有6個位置: ^$\b\B(?=p)(?!p)

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

/^^hello$$/.test('hello');  // true
/^^^hello$$/.test('hello'); // true

1. ^ 和 $

^ 匹配開頭,多行中匹配行開頭。
$ 匹配結尾,多行中匹配行結尾。

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

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

2. \b\B

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

"[HI] Leo_1.mp4".replace(/\b/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 爲一個子模式,即 (?=p) 匹配前面是 p 的位置,而 (?!p) 則匹配前面不是 p 的位置。

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

"hello".replace(/(?!l)/g, "#");
// "#h#ell#o#"

4. 相關案例

  • 匹配數字千位分隔符
// 匹配最後一個逗號
"12345678".replace(/(?=\d{3}$)/g, ","); // "12345,678"

// 匹配全部逗號
"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(/(?!\b)(?=(\d{3})+\b)/g, ","); 
// (?!\b) 等於 \B ,要求當前是一個位置,但不是 \b 前面的位置
// "12,345,678 123,456,789"
  • 數據格式化
let num = 1888;
num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ",").replace(/^/,"$$ ");
// "$ 1,888.00"
  • 驗證密碼
// 密碼長度 6-12 位數字或字母
let r = /^[0-9A-Za-z]{6,12}$/;

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

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

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


// 密碼長度 6-12 位數字或字母 
// 即 不能全是數字 或 不能全是大寫或小寫字母
let r = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;

3、正則表達式括號的使用

簡單理解:括號提供了分組,便於咱們使用它。

一般有兩種引用狀況:在JS代碼中引入,和在正則表達式中引入

分組和分支結構,主要是強調括號內是一個總體,即提供子表達式。

  • 分組如 /(ab)+/g 匹配連續出現的 ab
  • 分支結構如 /(a|b)+/g 匹配出現的 ab 表達式。

1.分組引用

如在日期匹配的時候,就能夠這麼改造:

// 原來
let r = /\d{4}-\d{2}-\d{2}/;

// 如今
let r = /(\d{4})-(\d{2})-(\d{2})/;
  • 提取數據
"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 轉成 mm/dd/yyyy

"2019-03-14".replace(r, "$2/$3/$1");
// 等價於
"2019-03-14".replace(r, function(){
    return RegExp.$2 + '/' + RegExp.$3 + '/' + RegExp.$1;
});

2. 反向引用

使用 \n 表示第 n 個分組,好比 \1 表示第 1 個分組:

let r = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
r.test("2019-03-15");
r.test("2019/03/15");
r.test("2019.03.15");
r.test("2019-03/15");
  • 多個括號嵌套

按照開括號的順序:

let r = /^((\d)(\d(\d)))\1\2\3\4$/;
let s = "1231231233";
r.test(s);
console.log([RegExp.$1,RegExp.$2,RegExp.$3,RegExp.$4]);
// ["123", "1", "23", "3"]
  • 特殊狀況

\10 表示的是第 10 個分組,若要匹配 \0 時,使用 (?:\1)0\1(?:0)

let r = /(1)(2)(3)(4)(5)(6)(7)(8)(9)(#) \10+/;
let s = "123456789# #####";
r.test(s);  // true
  • 當引用不存在的分組

如匹配 \2 是前面不存在,則匹配 \2 自己,即對 2 的轉義,不一樣瀏覽器可能不一樣:

let r = /\1\2\3\4/;
r.test("\1\2\3\4");  // true
"\1\2\3\4".split('');// ["", "", "", ""]
  • 分組後面有量詞

當分組後面有量詞的話,則捕獲的是最後一次的匹配:

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

/(\d)+ \1/.test("12345 1"); // false
/(\d)+ \1/.test("12345 5"); // true

3. 相關案例

這裏只寫出核心代碼。

  • 模擬字符串 trim 方法
// 1 匹配首尾空白符,替換成空字符
"  aaa   ".replace(/^\s+|\s+$/g, "");      // "aaa"

// 2 匹配整個字符串,再用引用提取對應數據
"  aaa   ".replace(/^\s*(.*?)\s*$/g, "$1");// "aaa"
  • 每一個單詞首字母大寫
"hi leo hi boy!".toLowerCase().replace(
    /(?:^|\s)\w/g, 
    c => c.toUpperCase()
);
// "Hi Leo Hi Boy!"
  • 駝峯化 和 中劃線化
"-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"
  • 匹配成對HTML標籤

匹配成對標籤 <h1>leo<\h1>,而不匹配不成對標籤 <h1>leo<\h2>

let r = /<([^>]+)>[\d\D]*<\/\1>/;
r.test("<h1>leo leo leo</h1>");  // true
r.test("<a>leo leo leo</a>");    // true
r.test("<h1>leo leo leo</h2>");  // false

4、正則表達式回溯法原理

概念理解起來比較容易。
好比用 /ab{1,3}c/ 去匹配下面兩個字符串。

  • 當匹配 abbbc,按順序匹配,到了第 3 個 b 後,直接匹配 c,這樣就沒有回溯。
  • 當匹配 abbc,按順序匹配,到了第 2 個 b 後,因爲規則是 b{1,3} ,則會繼續往下匹配,而後發現下一位是 c,因而回退到前一個位置,從新匹配,這就是回溯。

另外像 /".*"/ 來匹配 "abc"de 的話,就會有三個回溯狀況,爲了減小沒必要要的回溯,咱們能夠把正則修改成 /"[^"]*"/

介紹

回溯法,也稱試探法,本質上是深度優先探索算法,基本思路是:匹配過程當中後退到以前某一步從新探索的過程。

1. 常見的回溯形式

  • 貪婪量詞

多個貪婪量詞挨着存在,並相互衝突時,會看匹配順序,深度優先搜索:

"12345".match(/(\d{1,3})(\d{1,3})/);
//  ["12345", "123", "45", index: 0, input: "12345"]
  • 惰性量詞

有時候會由於回溯,致使實際惰性量詞匹配到的不是最少的數量:

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

"12345".match(/^\d{1,3}?\d{1,3}$/);
// 有回溯的狀況 ["12345", index: 0, input: "12345"]
  • 分支結構

分支機構,若是一個分支總體不匹配,會繼續嘗試剩下分支,也能夠當作一種回溯。

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

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

2. 本章小結

簡單總結:一個個嘗試,直到,要麼後退某一步總體匹配成功,要麼最後試完發現總體不匹配。

  • 貪婪量詞:買衣服砍價,價格高了,便宜點,再便宜點。
  • 懶惰量詞:賣衣服加價,價格低了,多給點,再多給點。
  • 分支結構:貨比三家,一家不行換一家,不行再換。

5、正則表達式的拆分

拆分正則代碼塊,是理解正則的關鍵。

在 JavaScrip 正則表達式有如下結構:

  • 字面量: 匹配一個具體字符,如 a 匹配字符 a
  • 字符組: 匹配一個有多種可能性的字符,如 [0-9] 匹配任意一個數字。
  • 量詞: 匹配一個連續出現的字符,如 a{1,3} 匹配連續最多出現 3 次的a字符。
  • 錨: 匹配一個位置,如 ^ 匹配字符串的開頭。
  • 分組: 匹配一個總體,如 (ab) 匹配 ab 兩個字符連續出現。
  • 分支: 匹配一個或多個表達式,如 ab|bc 匹配 abbc 字符。

另外還有如下操做符:

優先級 操做符描述 操做符
1 轉義符 \
2 括號和方括號 (...)/(?:...)/(?=...)/(?!...)/[...]
3 量詞限定符 {m}/{m,n}/{m,}/?/*/+
4 位置和序列 ^/$/\元字符/通常字符
5 管道符 ` `

Tips:優先級從上到下,由高到低。

1. 注意要點

  • 匹配字符串總體

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

  • 量詞連綴問題

須要匹配:每一個字符是 a/b/c 中其中一個,而且字符串長度是 3 的倍數:

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

  • 元字符轉義問題

元字符就是正則中的特殊字符,當匹配元字符就須要轉義,如:

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

// "[abc]"  => /\[abc\]/ 或者 /\[abc]/ 
// "{1,3}"  => /\{1\}/ 或者 /\{1}/ 由於不構成字符組

2. 案例分析

  • 身份證號碼
/^(\d{15}|\d{17})[\dxX]$/.test("390999199999999999");// true
  • IPV4地址

須要好好分析:

let r = /^((0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])$/

6、正則表達式的構建

正則的構建須要考慮如下幾點的平衡:

  • 匹配預期的字符串
  • 不匹配非預期的字符串
  • 可讀性和可維護性
  • 效率

咱們還須要考慮這麼幾個問題:

  • 是否須要使用正則

如能使用其餘 API 簡單快速解決問題就不須要使用正則:

"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"
  • 是否須要使用複雜正則

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

將這個正則拆分紅多個小塊,以下:

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. 準確性

即須要匹配到預期目標,且不匹配非預期的目標。

  • 匹配固定電話

如須要匹配下面固定電話號碼,能夠分別寫出對應正則:

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

而後合併:

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

而後提取公共部分:

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

再優化:

let r = /^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/
  • 匹配浮點數

先肯定,符號部分([+-])、整數部分(\d+)和小數部分(\.\d+)。

1.2三、+1.2三、-1.23  => /^[+-]?\d+\.\d+$/
十、+十、-10        => /^[+-]?\d+$/
.二、+.二、-.2        => /^[+-]?\.\d+$/

整理後:

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

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

// 考慮不匹配 012 這類 0 開頭的整數
let r = /^[+-]?(\d+)?(\.)?\d+$/;

2. 效率

正則表達式運行過程:

  1. 編譯
  2. 設定起始位置
  3. 嘗試匹配
  4. 若匹配失敗則返回前一步從新匹配
  5. 返回匹配成功失敗的結果

咱們經常優化對 3 和 4 步進行優化:

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

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

  • 使用非捕獲型分組

當不須要使用分組引用和反向引用時,此時可使用非捕獲分組。

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

  • 獨立出肯定字符

加快判斷是否匹配失敗,進而加快移位的速度。

/aa*/ 代替 /a+/

  • 提取分支公共部分

減小匹配過程當中可消除的重複。

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

  • 減小分支的數量,縮小它們的範圍

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

7、正則表達式編程

這裏要掌握正則表達式怎麼用,一般會有這麼四個操做:

  • 驗證
  • 切分
  • 提取
  • 替換

1. 四種操做

  • 驗證

匹配本質上是查找,咱們能夠藉助相關API操做:

// 檢查字符串是否包含數字
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. 相關API注意

  • searchmatch 參數問題

這兩個方法會把字符串轉換成正則,因此要加轉義

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"]

// 其餘不用轉義
s.split('.');
s.replace('.', '/');
  • match 返回結果的格式問題

match 參數有 g 會返回全部匹配的內容,沒有 g 則返回標準匹配格式:

let s = "2019.03.16";
s.match(/\b(\d+)\b/);  // ["2019", "2019", index: 0, input: "2019.03.16"]
s.match(/\b(\d+)\b/g); // ["2019", "03", "16"]
  • test 總體匹配時須要使用 ^$
/123/.test("a123b");    // true
/^123$/.test("a123b");  // false
/^123$/.test("123");    // true
  • split 的注意點

split 第二個參數是 結果數組的最大長度

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

使用正則分組,會包含分隔符:

"leo,pingan,pingan8787".split(/(,)/); // ["leo", ",", "pingan", ",", "pingan8787"]
  • 修飾符
修飾符 描述
g 全局匹配,即找到全部匹配的,單詞是 global
i 忽略字母大小寫,單詞是 ingoreCase
m 多行匹配,隻影響 ^$,兩者變成行的概念,即行開頭和行結尾。單詞是 multiline

文章到這結束,感謝閱讀,也感謝老姚大佬的這本書

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 https://github.com/pingan8787...
ES小冊 js.pingan8787.com

微信公衆號

bg

相關文章
相關標籤/搜索