ECMA 筆記之正則表達式

ECMA 筆記之正則表達式

一篇記錄了學習正則表達式的筆記。

1. 轉義字符

在 HTMl 中轉義字符以 & 符號開頭,分號;結尾。比如小於號(<)就可以寫 &lt; 或者 &#60,空格可以寫成 &nbsp;;

在 JavaScript 中轉義字符一般以反斜槓\開頭,比如回車(也叫行結束符\r)、換行(\n)、水平製表符(\t)、垂直製表符(\v)、換頁符(\f)。反斜槓則以兩個 \ 符號表示(即\\)。

// 轉義雙引號 
var str = "abcde\"fg";       

// 反斜槓
var str2 = "abcd\\efg"; 

// 換行符
var str2 = "abcd\nefg";     

// 回車換行符
var str3 = "abcd\r\nefg";   

// 水平製表符,相當於鍵盤上的 Tab 鍵 (\b 想當於鍵盤上的退格鍵)
var str4 = "abcd\tefg";      

2. 兩種創建正則的方法

有兩種創建正則表達式的方式,一種是直接量(字面量)語法,一種是通過內置的對象 RegExp。

2.1 直接量語法

/pattern/attributes

比如匹配字符串 abc

var reg = /abc/, str = "abcde";

console.log(reg.test(str)); 
// true

檢查字符串 str 中是否存在 abc

2.2 通過內置對象 RegExp

語法

new RegExp(pattern, attributes);

同樣是匹配字符串 abc

var reg = new RegExp("abc"), str = "abcde";

console.log(reg.test(str)); 
// true
new RegExp("[0-9_a-z]{2,10}").test('__')
// true

參數 pattern 的值可以是已有的正則表達式,但是如果在創建的時候不加關鍵字 new,返回的將是已有正則表達式的引用,而不是新創建的 RegExp 對象。

通過下面的兩個例子理解上一句話

  1. 使用 new 創建正則表達式:

    var reg = new RegExp("abc"), str = "abcde";
    
    var newReg = new RegExp(reg); 
    newReg.myAttr = "123";
    
    console.log(newReg.myAttr); 
    // "123"
    console.log(reg.myAttr);    
    // undefined
    
  2. 不使用 new 創建正則表達式:

    var reg = new RegExp("abc"), str = "abcde";
    
    var newReg = RegExp(reg); 
    newReg.myAttr = "123";
    
    console.log(newReg.myAttr); 
    // "123"
    console.log(reg.myAttr);    
    // "123"
    

2.3 參數

參數 pattern 是一個字符串,指定了正則表達式的模式或其他正則表達式。

參數 attributes 是一個可選的字符串,包含屬性 “g”、“i” 和 “m”,分別用於指定全局匹配、區分大小寫的匹配和多行匹配。ECMAScript 標準化之前,不支持 m 屬性。如果 pattern 是正則表達式,而不是字符串,則必須省略該參數。

簡單的說 pattern 就是我們寫的規則,而 attributes 是規則的修飾符。

修飾符 g,即 global,是否執行全局匹配

var reg = new RegExp("abc","g"), str = "abcdefgabc";

console.log(str.match(reg));   
// ["abc", "abc"]

// 查看正則表達式是否全局匹配
console.log(reg.global);      
// true 

使用全局匹配修飾符,匹配到兩個 "abc"。可以通過 reg.global 去判斷當前的正則表達式是否爲全局匹配。

修飾符 i,即 ignoreCase,是否忽略大小寫

var reg = new RegExp("abc","i"), str = "ABCDEFG";

console.log(str.match(reg));     
// ["ABC", index: 0, input: "ABCDEFG", groups: undefined]

// 查看正則表達式是否忽略大小寫
console.log(reg.ignoreCase);    
// true  

使用忽略大小寫修飾符,匹配到 "abc"。可以通過 reg.ignoreCase 去判斷當前的正則表達式是否忽略大小寫。

修飾符 m,即 multiline,是否以多行模式執行模式匹配

var reg = new RegExp("abc","gm"), str = "abcdefghjk\nabcde";

console.log(str.match(reg));     
// ["abc","abc"]

// 查看正則表達式是否以多行模式執行模式匹配
console.log(reg.multiline);    
// true   

使用多行匹配修飾符,匹配到兩個 "abc"。可以通過 reg.multiline 去判斷當前的正則表達式是否以多行模式執行模式匹配。

注意:所有的字符串如果不手動添加轉義字符 \n 都爲一行。

3. 字符組

在正則表達式中,字符組(一對方括號) [] 代表一位字符串的匹配範圍

例如,匹配字符串中三位連續的數字:

var reg = /[1234567890][1234567890][1234567890]/g, str = "12345asda7890";

console.log(str.match(reg)); 
// ["123", "789"]

當匹配到符合的字符串片段後,就從當前位置繼續向後匹配,不會回頭再去匹配。

匹配所有的數字可簡寫爲 [0-9],即 ASCII 碼中數字 0 到 9 範圍內的所有內容。

匹配所有的字母可簡寫 [A-z],所有的大寫字母可簡寫 [A-Z],所有的小寫字母可簡寫 [a-z]

4. 元字符

在正則表達式中,元字符(Metacharacter)是擁有特殊含義的字符。

4.1 元字符 .

元字符 .,用於查找單個字符,除了換行 \n 和行結束符 \r

var str = "That's hot!", patt1 = /h.t/g;

console.log(str.match(patt1));  
// "hat", "hot"

4.2 元字符 \w

元字符 \w,用於查找單詞字符(world),相當於 [0-9A-z_]

var str = "Give 100%!", patt1 = /\w/g;

console.log(str.match(patt1));   
// ["G", "i", "v", "e", "1", "0", "0"]

元字符 \W,用於查找非單詞字符,相當於 [^\w]

4.3 元字符 \d

元字符 \d,用於查找數字,即 [0-9]

var str = "Give 100%!", patt1 = /\d/g;

console.log(str.match(patt1));   
// [ "1", "0", "0"]

元字符 \D,用於查找非數字字符,相當於 [^\D]

4.4 元字符 \s

元字符 \s,用於查找空白字符,即 [\r\n\t\v\f ]

空白字符可以是:

  • 空格符 (space character)
  • 製表符 \t (tab character)
  • 回車符 \r (carriage return character)
  • 換行符 \n (new line character)
  • 垂直換行符 \v (vertical tab character)
  • 換頁符 \f (form feed character)
var str = "Is this all\nthere is?", patt1 = /\s/g;

console.log(str.match(patt1));   
// [" ", " ", "↵", " "]

元字符 \S,用於查找非空白字符,相當於 [^\s]

4.5 元字符 \b

元字符 \b,用於匹配單詞邊界

var str = "Is this all\nthere is?", patt1 = /\bt/g;

console.log(str.match(patt1));  
 // ["t", "t"]

元字符 \B,用於查找非單詞邊界,相當於 [^\b]

var str = "Is this all\nthere is?", patt1 = /(\bthis\b|\bt\B)/g;

console.log(str.match(patt1));   
// ["this", "t"]

4.6 元字符 \xxx

\xxx 元字符用於查找以八進制數 xxx 規定的字符

對字符串中的八進制 127 (W) 進行全局搜索:

var str = "Hello World or word!", patt1 = /\127/g;

console.log(str.match(patt1));   
// ["W"]

忽略大小寫呢?

var str = "Hello World or word!", patt1 = /\127/gi;

console.log(str.match(patt1));   
// ["W", "W"]

4.7 元字符 \xdd

\xdd 元字符查找以十六進制數 dd 規定的字符

對字符串中的十六進制 57 (W) 進行全局搜索:

var str = "Hello World or word!", patt1 = /\x57/g;

console.log(str.match(patt1));   
// ["W"]

4.8 元字符 \uxxxx

\uxxxx 元字符用於查找以十六進制數 xxxx 規定的 Unicode 字符

對字符串中的十六進制 0057 (W) 進行全局搜索:

var str = "Hello World or word!", patt1 = /\u0057/g;

console.log(str.match(patt1));   
// ["W"]

因爲計算機只能處理數字,如果要處理文本,就必須先把文本轉換爲數字才能處理。

Unicode(統一碼、萬國碼、單一碼)是計算機科學領域裏的一項業界標準,包括字符集、編碼方案等。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。

 "\u54c8\u55bd" // 哈嘍

5. 量詞(限定符)

量詞,也叫限定符,用於描述前面字符(分組)可以出現的次數。

注意:在此節中,變量 n 可以代表任何字符。

5.1 量詞 n+

量詞 n+,匹配變量 n 至少出現 1 次。

var str = "Hello World or word!", patt1 = /o+/g;

console.log(str.match(patt1));   
// ["o", "o", "o", "o"]

5.2 量詞 n*

量詞 n*,匹配變量 n 出現 0 次到無數次(至少出現 0 次)。

var str = "or oo", patt1 = /o*/g;

console.log(str.match(patt1));  
 // ["o", "", "", "oo", ""]   "oo" -> 貪婪匹配

5.3 量詞 n?

量詞 n?,匹配變量 n 出現 0 次或 1 次。

var str = "or oo", patt1 = /o?/g;

console.log(str.match(patt1));   
// ["o", "", "", "o", "o", ""]

5.4 量詞 n{X}

量詞 n{X},匹配變量 n 出現 X 次。

var str = "or oo ooo", patt1 = /o{2}/g;

console.log(str.match(patt1));   
// ["oo", "oo"]

5.5 量詞 n{X,Y}

量詞 n{X,Y},匹配變量 n 出現 X 次到 Y 次。

var str = "or oo ooo", patt1 = /o{2,3}/g;

console.log(str.match(patt1));   
// ["oo", "ooo"]

5.6 量詞 n{X,}

量詞 n{X,},匹配變量 n 至少出現 X 次。

var str = "or oo ooo", patt1 = /o{1,}/g;

console.log(str.match(patt1));   
// ["o", "oo", "ooo"]

5.7 量詞 ^n

量詞 ^n,匹配任何開頭爲 n 的字符串。

var str = "abc def", str2 = "db cefc", patt1 = /^d/g;

console.log(str.match(patt1));   
// null
console.log(str2.match(patt1));  
// ["d"]

字符串 "abc def"a 開頭。

5.8 量詞 n$

量詞 n$,匹配任何結尾爲 n 的字符串。

var str = "abc def", str2 = "ab defc", patt1 = /c$/g;

console.log(str.match(patt1));   
// null
console.log(str2.match(patt1));  
// ["c"]

量次 ^$ 同時出現,字符串只能是中間的內容

var str = "abcdabcd", str2 = "abcd", patt1 = /^abcd$/g;

console.log(str.match(patt1));   
// null
console.log(str2.match(patt1));  
// ["abcd"]

5.9 量詞 ?=n

量詞 ?=n,匹配任何其後緊接指定字符串 n 的字符串。

例如,對其後緊跟 “all” 的 “is” 進行全局搜索:

var str="Is this all there is";
var patt1=/is(?= all)/g;

console.log(str.match(patt1));   
// ["is"]

量詞 ?=n,也稱爲正向預查(正向斷言)。

5.10 量詞 ?!n

量詞 ?!n,匹配任何其後沒有緊接指定字符串 n 的字符串。

對其後沒有緊跟 “all” 的 “is” 進行全局搜索:

var str="Is this all there is";
var patt1=/is(?! all)/gi;

console.log(str.match(patt1));  
// ["Is", "is"]

量詞 ?!n,也有稱爲非正向預查(非正向斷言)。

6. 分組與反向引用

限制單個字符的出現次數,直接在後面加上量詞即可。但是如果我們要同時限制多個字符呢?我們可以通過括號 () 把需要一起限制的字符括在一起,再在括號的後面加上量詞。

var str = "aa1bba123bcda123123bbbba123123123b3w";
var reg = /a(123){1,3}b/g; 

console.log(str.match(reg)); 
// ["a123b", "a123123b", "a123123123b"]

用括號 () 把多個字符包裹起來,這個行爲稱之爲分組,被括號包裹起來的字符被稱爲子表達式

例如,/(abc)\d/g匹配所有 abc 後面緊跟一位數字的字符片段。

分組可以用來提取字符:

var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/;
var str = "2019-1-9", str2 = "2019-1-19", str3 = "2018-11-19";

console.log(str.match(reg));
// ["2019-1-9", "2019", "1", "9", index: 0, input: "2019-1-9", groups: undefined]
console.log(str2.match(reg));
// ["2019-1-19", "2019", "1", "19", index: 0, input: "2019-1-19", groups: undefined]
console.log(str3.match(reg));
// ["2018-11-19", "2018", "11", "19", index: 0, input: "2018-11-19", groups: undefined]

6.1 可捕獲的分組

我們直接通過括號 () 進行的分組默認就是可捕獲的。

通過反向引用可以引用前面子表達式匹配的內容。反向引用以反斜槓 \ 開頭,後面緊跟數字 123456789... ,數字爲幾就代表引用第幾個子表達式的值。

例如,\1 匹配第一個子表達式中匹配的內容:

var str = "aa asd dd";
var reg = /(\w)\1/g; 

console.log(str.match(reg)); 
// ["aa", "dd"]

子表達式的值可以重複引用:

var str = "aaaa";
var reg = /(\w)\1\1\1/g; 

console.log(str.match(reg)); 
// ["aaaa"]

如果引用的是不存在的分組:

var str = "aaaa\3", str2 = "aabb\3";
var reg = /(\w)\1(\w)\2\3/g; 

console.log(str.match(reg));   
// ["aaaa"]
console.log(str2.match(reg));  
// ["aabb"]

當引用了不存在的子表達式時,匹配反向引用的字符本身。例如, \3就配 \3

可捕獲的分組也可以替換字符:

var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/;
var str = "2019-1-9", str2 = "2019-1-19", str3 = "2018-11-19";

console.log(str.replace(reg,'$1/$2/$3'));
// 2019/1/9
console.log(str2.replace(reg,'$1/$2/$3'));
// 2019/1/19
console.log(str3.replace(reg,'$1/$2/$3'));
// 2018/11/19

6.2 不可捕獲的分組

我們知道默認的分組是可捕獲的。但是所有的分組都可以捕獲在某些情況下是不需要的。

可以使用非捕獲括號 (?:n) 達到我們的目的,n 爲我們自己的子表達式。

var str = "aa1bba123bcda123123bbbba123123123b3w";
var reg = /a(?:123){1,3}b/g; 

console.log(str.match(reg)); 
// ["a123b", "a123123b", "a123123123b"]

可捕獲的分組捕獲的內容會被存儲在內存中,不可捕獲的分組則不會捕獲文本,也不會將它匹配到的內容單獨分組來放到內存中。

所以,如果我們使用的分組不用捕獲應該使用不可捕獲的分組,更節省內存。

7. 或 與 非

7.1 或(分支) |

在正則表達式中,管道符 | (分支)的意思,只要滿足一個分子就可匹配成功。

管道符 | 可用於子表達式 () 中:

var reg = /(123|456|789)[A-z]/g, str = "123bb45ccc";

console.log(str.match(reg)); 
// ["123b"]

也可用於表達式(方括號) [] 中:

var reg = /[123|456|789][A-z]/g, str = "1aa4Ab5Cc6E";

console.log(str.match(reg)); 
// ["1a", "4A", "5C", "6E"]

甚至就寫在正則中。例如,檢查一個字符串的首尾是否存在數字:

var reg = /^\d|\d$/g, str = "1ab";

console.log(reg.test(str)); 
// true

7.2 非 ^

符號 ^ 在正則表達式不同的位置擁有不同的含義:

  • /^abc/ - 在正則表達式的 頭部 表示匹配以 abc 開頭的字符串(符號 $ 匹配字符串的結束)。
  • /[^abc]/ - 放在正則表達式的 字符組 中則表示匹配除了 abc 以外的所有字符(非)。

放在正則表達式頭部:

var reg = /^abc/g, str = "abcdefg", str2 = "123abcdefg";

console.log(str.match(reg));   
// ["abc"]
console.log(str2.match(reg));   
// null

第二行的頭部也是可以匹配到的:

var reg = /^abc/gm, str = "123abcdefg\nabcs";

console.log(str.match(reg)); 
// ["abc"]

符號 ^ 放在表達式中意思爲 ,即匹配除了這些以外的所有字符

var reg = /[^abc]/g, str = "abcdefg";

console.log(str.match(reg)); 
// ["d", "e", "f", "g"]

8. 沒想好寫啥

9. 貪婪匹配與非貪婪匹配

量詞 默認使用的就是貪婪匹配,它會盡可能多的去匹配符合規則的字符串。

var str = "aaaaaaaaa", reg = /a+/g;

console.log(str.match(reg)); 
// ["aaaaaaaaa"]

貪婪匹配轉換爲非貪婪匹配,在量詞後加上符號 ? 即可

var str = "aaaaaaaaa", reg = /a+?/g;

console.log(str.match(reg)); 
// ["a", "a", "a", "a", "a", "a", "a", "a", "a"]
var str = "11222333", reg = /\d{2,3}?/g;

console.log(str.match(reg)); 
// ["11", "22", "23", "33"]
var str = "11222333", reg = /\d??/g;

console.log(str.match(reg)); 
// ["", "", "", "", "", "", "", "", ""]

量詞 n? ,表示匹配出現 0 次或者 1 次,再加上一個符號 ? 轉換爲非貪婪匹配,那麼匹配的就是 0 次。

10. RegExp 對象屬性

global 屬性用於判斷某個正則表達式是否具有修飾符 g

ignoreCase 屬性用於判斷某個正則表達式是否具有修飾符 i

multiline 屬性用於判斷某個正則表達式是否具有修飾符 m

lastIndex 屬性標示下一次匹配的字符位置。常與 exec() 方法一起出現。

source 屬性用於返回模式匹配所用的文本。

一個例子加深理解:

var str = "www.abc.com\n123.ab.cn";
var reg = /\w\./gm;

console.log(reg.lastIndex);  // 0
console.log(str.match(reg)); // ["w.", "c.", "3.", "b."]
console.log(reg.global);     // true
console.log(reg.ignoreCase); // false
console.log(reg.multiline);  // true
console.log(reg.source);     // "\w\."

reg.lastIndex = 4;
console.log(reg.lastIndex);  // 4
console.log(str.match(reg)); // ["w.", "c.", "3.", "b."]

reg.lastIndex = 4;
console.log(reg.lastIndex); // 4
console.log(reg.exec(str)); // ["c.", index: 6, input: "www.abc.com↵123.ab.cn", groups: undefined]
console.log(reg.lastIndex); // 8
console.log(reg.exec(str)); // ["3.", index: 14, input: "www.abc.com↵123.ab.cn", groups: undefined]
console.log(reg.lastIndex); // 16
console.log(reg.exec(str)); // ["b.", index: 17, input: "www.abc.com↵123.ab.cn", groups: undefined]
console.log(reg.lastIndex); // 19
console.log(reg.exec(str)); // null
console.log(reg.lastIndex); // 0

exec() 當匹配到符合規則的字符時便會停下,等待下一次調用,直到字符串匹配結束。

11. RegExp 對象方法

11.1 test() 方法

test() 方法用於檢測一個字符串是否匹配某個模式.

語法

RegExpObject.test(string)

如果字符串 string 中含有與 RegExpObject 匹配的文本,則返回 true,否則返回 false。

比如,檢索 “www”

var str = "www.abc.com";
var patt1 = /www/;

console.log(patt1.test(str));   
// true

11.2 exec() 方法

exec() 方法用於檢索字符串中的正則表達式的匹配。

語法

RegExpObject.exec(string)

如果 exec() 找到了匹配的文本,則返回一個結果數組。否則,返回 null。

在上一次匹配的基礎上接着匹配。

var reg = /ab/g;
var str = "abababab";

console.log(reg.lastIndex); // 0 -> 當前開始匹配的索引位置
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 2
console.log(reg.exec(str)); // ["ab", index: 2, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 4
console.log(reg.exec(str)); // ["ab", index: 4, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 6
console.log(reg.exec(str)); // ["ab", index: 6, input: "abababab", groups: undefined]
console.log(reg.lastIndex); // 8
console.log(reg.exec(str)); // null
console.log(reg.lastIndex); // 0
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]

exec() 當匹配到符合規則的字符時便會停下,等待下一次調用,直到字符串匹配結束。

reg.lastIndex 是可讀寫的。

var reg = /ab/g;
var str = "abababab";

console.log(reg.lastIndex); // 0 -> 當前開始匹配的索引位置
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]
reg.lastIndex = 0;       
console.log(reg.exec(str)); // ["ab", index: 0, input: "abababab", groups: undefined]

注意:如果不加修飾符 g,永遠從索引 0 開始匹配。

11.3 exec() 方法與子表達式 ()

還是上面那個例子,但是使用 exec() 方法去匹配

var str = "aaaa", str2 = "aabb";
var reg = /(\w)\1(\w)\2/g; 

console.log(reg.exec(str2));   
// ["aabb", "a", "b", index: 0, input: "aabb", groups: undefined]

此類數組的第 0 個元素是與正則表達式相匹配的文本,第 1 個元素是與 RegExpObject 的第 1 個子表達式相匹配的文本(如果有的話),第 2 個元素是與 RegExpObject 的第 2 個子表達式相匹配的文本(如果有的話),以此類推。

index 屬性聲明的是匹配文本的第一個字符的位置。input 屬性則存放的是被檢索的字符串 string。

11.4 compile() 方法

compile() 方法用於在腳本執行過程中編譯正則表達式。

compile() 方法也可用於改變和重新編譯正則表達式。

該特性已經從 Web 標準中刪除,雖然一些瀏覽器目前仍然支持它,但也許會在未來的某個時間停止支持,請儘量不要使用該特性。

語法

RegExpObject.compile(regexp,modifier)
  • 參數 regexp 爲正則表達式。

  • 參數 modifier 爲修飾符。

不推薦compile方法。你可以使用 RegExp 構造函數來得到相同效果。

12. 字符串上使用正則表達式

12.1 字符串的 match() 方法

同樣的例子使用 match() 方法:

var str = "aabb";
var reg = /(\w)\1(\w)\2/g; 

console.log(str.match(reg));   
// ["aabb"]

如果不加全局修飾符 g 呢:

var str = "aabb";
var reg = /(\w)\1(\w)\2/; 

console.log(str.match(reg));   
// ["aabb", "a", "b", index: 0, input: "aabb", groups: undefined]

加了全局修飾符後結果與使用 exec() 方法類似。

12.2 字符串的 search() 方法

search() 方法返回匹配到字符串的位置。

var str = "123aabb";
var reg = /(\w)\1(\w)\2/; 

console.log(str.search(reg));  
// 3

如果匹配不到則返回 -1

var str = "123abcd";
var reg = /(\w)\1(\w)\2/; 

console.log(str.search(reg));   
// -1

12.3 字符串的 split() 方法

split() 方法以特定的規則去拆分字符串:

var str = "ab0c2de2f4gh5d";
var reg = /\d/g; 

console.log(str.split(reg));   
// ["ab", "c", "de", "f", "gh", "d"]

以數字爲界限去拆分字符串

12.4 字符串的 replace() 方法

replace() 方法以特定的規則去替換字符串:

var str = "what is you name?";

console.log(str.replace("a","b"));   
// "whbt is you name?"

把第一個 "a" 替換爲 "b"

注意,replace() 方法第一個參數不是正則表達式時,無法訪問全局。

使用正則表達式:

var reg = /a/g; 
var str = "what is you name?";

console.log(str.replace(reg,"b"));   
// "whbt is you nbme?"

把所有的 "a" 替換爲 "b"

replace() 方法可引用子表達式匹配到的值,例如,如何把形如 XXYY 的字符串變成 YYXX。

var reg = /(\w)\1(\w)\2/g; 
var str = "aabb 123 1122";

console.log(str.replace(reg,"$2$2$1$1"));   
// "bbaa 123 2211"

replace() 方法的第二個參數可以通過 $1 去引用第一個子表達式匹配到的值。 同理 $2 爲第二個。

把某個字符替換爲 $:

// 在 `replace()` 方法中,符號 `$` 有轉義的意思,若想把某個字符替換爲 `$`,最好寫爲 `$$`:
var reg = /(\w)\1/g; 
var str = "aabb 123 1122";

console.log(str.replace(reg,"$"));   // "$$ 123 $$"
console.log(str.replace(reg,"$$"));  // "$$ 123 $$"
console.log(str.replace(reg,"$1"));  // "ab 123 12"

replace() 方法可傳入回掉函數:

var reg = /(\w)\1(\w)\2/g; 
var str = "aabb 123 1122";

console.log(str.replace(reg, function(val, $1, $2){
    // val 爲全局結果   $1 爲第一個子表達式匹配到的值   $2 ...
    return $2 + $2 + $1 + $1
}));   // "bbaa 123 2211"

13. 實例

實例 1,the-first-name 轉爲 theFirstName

var reg = /-(\w)?/g; 
var str = "the-first-name";

console.log(str.replace(reg, function(val, $1){
    return $1 ? $1.toUpperCase() : ""
}));   // "theFirstName"

反向轉換:

var reg = /([A-Z])/g; 
var str = "theFirstName";

console.log(str.replace(reg, function(val, $1){
    return "-" + $1.toLowerCase()
}));  // the-first-name

實例 2,字符串簡單去重 aaabbcccdd -> abcd

// 反向引用多個
var reg = /(\w)\1+/g; 
var str = "aaabbcccadd";

console.log(str.replace(reg, "$1"));   
// "abcd"

實例 3,格式化數字 100000000 -> 100.000.000

var reg = /\B(?=(\d{3})+(?!\d))/g; 
var str = "100000000000000";

console.log(str.replace(reg, "."));   
// "100.000.000.000.000"
var reg = /\B(?=(\d{3})+$)/g; 
var str = "100000000000000";

console.log(str.replace(reg, "."));   
// "100.000.000.000.000"
var reg = /(?=\B(\d{3})+$)/g; 
var str = "10000000000000000";

console.log(str.replace(reg, "."));   
// "10.000.000.000.000.000"

實例 4,匹配成對的 HTML 標籤

var reg = /<([^>]+)>[\w\W]*<\/\1>/g; 
var str = "<div><h1>asdasd</h1></div>", str2 = "<p>asdasd</p>", str3 = "<div>asdasd</p>";

console.log(str.match(reg));
// "<div><h1>asdasd</h1></div>"
console.log(str2.match(reg));   
// ["<p>asdasd</p>"]
console.log(str3.match(reg)); 
// null

標籤中不包含標籤:

var reg = /<([^>]+)>[^<>]*<\/\1>/g; 
var str = "<div><h1>asdasd</h1></div>", str2 = "<p>asdasd</p>", str3 = "<div>asdasd</p>";

console.log(str.match(reg));
// "<h1>asdasd</h1>"
console.log(str2.match(reg));   
// ["<p>asdasd</p>"]
console.log(str3.match(reg)); 
// null

實例5

// 數字範圍 2-64
/^(0?[2-9]|[1-5][0-9]|6[0-4])$/.test(53)
// true

14. 學習資料

w3school 的 RegExp 對象

MDN web docs

《JavaScript 正則表達式迷你書》

渡一教育-正則表達式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章