JavaScript之正則表示式小記
文章目錄
JavaScript之正則表示式小記
一篇記錄了正則表示式基礎的筆記。
通過有道雲筆記閱讀體驗感覺更乾淨些,就是載入比較慢~
轉義字元
在 HTMl 中轉義字元以 &
符號開頭,分號;
結尾。比如小於號(<
)就可以寫 <
或者 <
,空格可以寫成
在JavaScript 中轉義字元一般以反斜槓""開頭,比如回車(\r
)、換行(\n
)、水平製表符(\t
)、垂直製表符(\v
)、換頁符(\f
)。反斜槓則以兩個\
表示(即\\
)。
// 轉義雙引號
var str = "abcde\"fg";
// 換行符
var str2 = "abcd\nefg";
// 回車換行符
var str3 = "abcd\r\nefg";
// 水平製表符,相當於鍵盤上的 Tab 鍵 (\b 想當於鍵盤上的退格鍵)
var str4 = "abcd\tefg";
兩種建立正則的方法
有兩種建立正則表示式的方式,一種是直接量(字面量)語法,一種是通過內建的物件 RegExp。
直接量語法
/pattern/attributes
比如匹配字串 abc
:
var reg = /abc/, str = "abcde";
console.log(reg.test(str));
// true
檢查字串 str
中是否存在 abc
。
通過內建物件 RegExp
語法
new RegExp(pattern, attributes);
同樣是匹配字串 abc
:
var reg = new RegExp("abc"), str = "abcde";
console.log(reg.test(str));
// true
引數 pattern 的值可以是已有的正則表示式,但是如果在建立的時候不加關鍵字 new
,返回的將是已有正則表示式的引用,而不是新建立的 RegExp 物件。
通過下面的兩個例子理解上一句話
-
使用
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
-
不使用
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"
引數
引數 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
都為一行。
表示式(方括號)
在正則表示式中,一對方括號代表一位字串的匹配範圍。
例如,匹配字串中三位連續的數字:
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]
。
非 ^
符號 ^
在正則表示式不同的位置擁有不同的含義:
/^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"]
或 |
在正則表示式中,符號 |
為 或 的意思
符號 |
可用於子表示式 ()
中:
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
元字元
在正則表示式中,元字元(Metacharacter)是擁有特殊含義的字元。
- 元字元
.
,用於查詢單個字元,除了換行和行結束符。
var str = "That's hot!", patt1 = /h.t/g;
console.log(str.match(patt1));
// "hat", "hot"
- 元字元
\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]
。
- 元字元
\d
,用於查詢數字,即[0-9]
。
var str = "Give 100%!", patt1 = /\d/g;
console.log(str.match(patt1));
// [ "1", "0", "0"]
元字元 \D
,用於查詢非數字字元,相當於 [^\D]
。
- 元字元
\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]
。
- 元字元
\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"]
\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"]
\xdd
元字元查詢以十六進位制數dd
規定的字元。
對字串中的十六進位制 57 (W) 進行全域性搜尋:
var str = "Hello World or word!", patt1 = /\x57/g;
console.log(str.match(patt1));
// ["W"]
\uxxxx
元字元用於查詢以十六進位制數xxxx
規定的 Unicode 字元。
對字串中的十六進位制 0057 (W) 進行全域性搜尋:
var str = "Hello World or word!", patt1 = /\u0057/g;
console.log(str.match(patt1));
// ["W"]
因為計算機只能處理數字,如果要處理文字,就必須先把文字轉換為數字才能處理。
Unicode(統一碼、萬國碼、單一碼)是電腦科學領域裡的一項業界標準,包括字符集、編碼方案等。Unicode 是為了解決傳統的字元編碼方案的侷限而產生的,它為每種語言中的每個字元設定了統一併且唯一的二進位制編碼,以滿足跨語言、跨平臺進行文字轉換、處理的要求。
"\u54c8\u55bd" // 哈嘍
量詞
變數 n
可以代表任何字元。
量詞 n+
,表示變數 n
至少出現 1 次。
var str = "Hello World or word!", patt1 = /o+/g;
console.log(str.match(patt1));
// ["o", "o", "o", "o"]
量詞 n*
,表示變數 n
可以出現 0 次到無數次。
var str = "or oo", patt1 = /o*/g;
console.log(str.match(patt1));
// ["o", "", "", "oo", ""] "oo" -> 貪婪匹配
量詞 n?
,表示變數 n
可以出現 0 次或 1 次。
var str = "or oo", patt1 = /o?/g;
console.log(str.match(patt1));
// ["o", "", "", "o", "o", ""]
量詞 n{X}
,表示變數 n
可以出現 X 次。
var str = "or oo ooo", patt1 = /o{2}/g;
console.log(str.match(patt1));
// ["oo", "oo"]
量詞 n{X,Y}
,表示變數 n
可以出現 X 次到 Y 次。
var str = "or oo ooo", patt1 = /o{2,3}/g;
console.log(str.match(patt1));
// ["oo", "ooo"]
量詞 n{X,}
,表示變數 n
至少出現 X 次。
var str = "or oo ooo", patt1 = /o{1,}/g;
console.log(str.match(patt1));
// ["o", "oo", "ooo"]
量詞 ^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
開頭
量詞 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"]
量詞 ?=n
,匹配匹配任何其後緊接指定字串 n 的字串。
對其後緊跟 “all” 的 “is” 進行全域性搜尋:
var str="Is this all there is";
var patt1=/is(?= all)/g;
console.log(str.match(patt1));
// ["is"]
量詞 ?=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
,也有稱為非正向預查(非正向斷言)。
貪婪匹配與非貪婪匹配
上一節所說的 量詞 預設使用的是貪婪匹配,它會盡可能多的去匹配符合規則的字串。
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 次。
子表示式 ()
括號 ()
中的內容稱為子表示式
\1
匹配第一個子表示式中匹配的內容
// 匹配第一個子表示式中匹配的內容(反向引用第一個子表示式匹配的內容)
var reg = /(\w)\1/g;
var str = "aaaa";
var reg = /(\w)\1\1\1/g;
console.log(str.match(reg));
// ["aaaa"]
\2
匹配第二個子表示式中匹配的內容,有幾個子表示式就可以寫到幾。
var str = "aaaa", str2 = "aabb";
var reg = /(\w)\1(\w)\2/g;
console.log(str.match(reg));
// ["aaaa"]
console.log(str2.match(reg));
// ["aabb"]
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()
當匹配到符合規則的字元時便會停下,等待下一次呼叫,直到字串匹配結束。
RegExp 物件方法
test()
方法
test()
方法用於檢測一個字串是否匹配某個模式.
語法
RegExpObject.test(string)
如果字串 string 中含有與 RegExpObject 匹配的文字,則返回 true,否則返回 false。
比如,檢索 “www”
var str = "www.abc.com";
var patt1 = /www/;
console.log(patt1.test(str));
// true
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 開始匹配。
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。
compile()
方法
compile()
方法用於在指令碼執行過程中編譯正則表示式。
compile()
方法也可用於改變和重新編譯正則表示式。
該特性已經從 Web 標準中刪除,雖然一些瀏覽器目前仍然支援它,但也許會在未來的某個時間停止支援,請儘量不要使用該特性。
語法
RegExpObject.compile(regexp,modifier)
-
引數 regexp 為正則表示式。
-
引數 modifier 為修飾符。
不推薦compile方法。你可以使用 RegExp 建構函式來得到相同效果。
字串上使用正則表示式
字串的 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()
方法類似。
字串的 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
字串的 split()
方法
split()
方法以特定的規則去拆分字串:
var str = "ab0c2de2f4gh5d";
var reg = /\d/g;
console.log(str.split(reg));
// ["ab", "c", "de", "f", "gh", "d"]
以數字為界限去拆分字串
字串的 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"
練習,the-first-name 轉為 theFirstName
var reg = /-(\w)/g;
var str = "the-first-name";
console.log(str.replace(reg, function(val, $1){
return $1.toUpperCase()
})); // "theFirstName"