正則表達式(Regular Expression)是一組由字母和符號組成的特殊文本,它可以用來從文本中找出滿足你想要的格式的句子。

創(chuàng)建正則表達式的兩種方法:字面量、RegExp 構造函數(shù)
字面量,以斜杠表示開始和結束:
const regex = /abc/
RegExp 構造函數(shù):
const regex = new RegExp('abc')
RegExp 構造函數(shù)還可以接受第二個參數(shù),表示修飾符:
const regex = new RegExp('abc', 'i')
實例方法
test()
test() 方法返回一個布爾值,表示當前模式是否能匹配參數(shù)字符串。
/lit/.test('I am a lit') // true
exec()
exec() 方法在一個指定字符串中執(zhí)行一個搜索匹配。返回一個結果數(shù)組或 null。
const str = '_x_x'
/x/.exec(str) // ['x', index: 1, input: '_x_x', groups: undefined]
/y/.exec(str) // null
實例屬性
-
ignoreCase只讀屬性。返回一個布爾值,表示是否設置了i修飾符。 -
multiline只讀屬性。返回一個布爾值,表示是否設置了m修飾符。 -
global只讀屬性。返回一個布爾值,表示是否設置了g修飾符。
const reg = /abc/igm
reg.ignoreCase // true
reg.global // true
reg.multiline // true
Tips:這些修飾符的作用下文有做解釋。
lastIndex 可讀可寫。返回一個數(shù)值,表示下一次開始搜索的位置。
/(hi)?/g.lastIndex // 0
source 只讀屬性。返回正則表達式的字符串形式(不包括反斜杠)。
/abc/igm.source // "abc"
unicode 只讀屬性。屬性表明正則表達式帶有 u 修飾符。
/\u{61}/u.unicode // true
sticky ES6 新增的只讀屬性。表示是否設置了y修飾符。
/foo/y.sticky // true
flags ES6 新增。該屬性返回一個字符串,由當前正則表達式對象的修飾符組成,以字典序排序(從左到右,即 "gimuy")。
/foo/ig.flags // "gi"
/bar/myu.flags .flags // "muy"
字符串的正則方法
match()
match() 方法檢索返回一個字符串匹配正則表達式的結果數(shù)組。
'The fat cat sat on the mat.'.match(/a/g) // ["a", "a", "a", "a"]
split()
split() 按照給定規(guī)則進行字符串分割,返回一個數(shù)組,包含分割后的各個成員。
語法
str.split(separator, [limit])
該方法接受兩個參數(shù),第一個參數(shù)是正則表達式,表示分隔規(guī)則,第二個參數(shù)是返回數(shù)組的最大成員數(shù)。
示例
'The fat cat sat on the mat.'.split(' ', 3) // ["The", "fat", "cat"]
"Hello 1 word. Sentence number 2.".split(/(\d)/) // ["Hello ", "1", " word. Sentence number ", "2", "."]
replace()
replace() 按照給定的正則表達式進行替換,返回替換后的字符串。
語法
str.replace(regexp|substr, newSubStr|function)
示例
const str = 'Twas the night before Xmas...'
const newstr = str.replace(/xmas/i, 'Christmas')
str // "Twas the night before Xmas..."
newstr // "Twas the night before Christmas..."
原字符串不會改變。
search()
search() 按照給定的正則表達式進行搜索,返回一個整數(shù),表示匹配開始的位置。如果沒有任何匹配,則返回 -1。
'The fat cat sat on the mat.'.search('at') // 5
'The fat cat sat on the mat.'.search('v') // -1
matchAll()
matchAll() ES2020 新增方法。該方法返回一個包含所有匹配正則表達式的結果及分組捕獲組的迭代器(Iterator)。
const str = 'test1test2'
const reg = /t(e)(st(\d?))/g
for (const match of str.matchAll(reg)) {
console.log(match)
}
// ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', groups: undefined]
// ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', groups: undefined]
// 轉為數(shù)組
const array = [...str.matchAll(reg)]
// const array = Array.from(str.matchAll(reg))
array[0] // ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', groups: undefined]
array[1] // ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', groups: undefined]
元字符
| 元字符 | 描述 |
|---|---|
. |
匹配任意單個任何字符,除了換行符 |
[ ] |
字符種類。匹配方括號內的任意字符。 |
[^] |
否定的字符種類。匹配除了方括號里的任意字符。 |
* |
匹配 >=0 個重復的在 * 號之前的字符。 |
+ |
匹配 >=1 個重復的 + 號前的字符。 |
? |
標記 ? 之前的字符為可選。 |
{n, m} |
匹配 num 個大括號之前的字符或字符集 (n <= num <= m)。 |
(xyz) |
字符集,匹配與 xyz 完全相等的字符串。 |
\ |
轉義字符,用于匹配一些保留的字符 `[ ] ( ) { } . * + ? ^ $ \ |
^ |
從開始行開始匹配。 |
$ |
從末端開始匹配。 |

使用或運算符(|)在用 Markdown 表格上顯示有問題,貼出圖片。(倒數(shù)第三個元字符描述缺少 | 同樣問題)
分組
(abc) |
捕獲組 |
|---|---|
(?:abc) |
匹配,但不捕獲 abc
|

量詞
a* |
匹配 0 或更多 |
|---|---|
a+ |
匹配 1 或更多 |
a? |
匹配 0 或 1 |
a{5} |
精確匹配 5 |
a{,3} |
最多匹配 3 個 |
a{3,} |
匹配 3 或更多 |
a{1,3} |
1 和 3 之間的匹配 |
錨點
\G |
匹配開始 |
|---|---|
^、\A
|
字符串開頭 |
$、\Z
|
字符串結尾 |
\z |
字符串絕對結尾 |
\b |
單詞邊界 |
\B |
非單詞邊界 |
^abc |
以 abc 結尾 |
abc$ |
以 abc 開頭 |
轉義字符
上面所提到的有特殊含義的元字符,如果要匹配它們本身,就需要在它們前面要加上反斜杠。比如要匹配 +,就要寫成 \+。
\. \* \\ |
正則表達式使用的轉義特殊字符 |
|---|---|
\t |
Tab 制表鍵 |
\n |
換行符 |
\r |
回車 |
/1+1/.test('1+1') // false
(/1\+1/).test('1+1') // true
如果使用 RegExp 方法生成正則對象,轉義需要使用兩個斜杠,因為字符串內部會先轉義一次。
const reg = new RegExp('1\+1')
reg.test('1+1') // false
const reg1 = new RegExp('1\\+1')
reg1.test('1+1') // true
字符集
字符集也叫做字符類。方括號 [] 用來指定一個字符集。 在方括號中使用連字符來指定字符集的范圍。 在方括號中的字符集不關心順序。
[abc] |
a、b 或 c 中的任何一種 |
|---|---|
[a-z] |
介于和 a 和 z 之間的字符 |
[1-9] |
介于和 1 和 9 之間的數(shù)字 |
[[:print:]] |
包括空格在內的任何可打印字符 |
[^abc] |
除了 a、b 或 c 以外的任何字符 |
簡寫字符集
. |
除換行符外的所有字符 |
|---|---|
\w |
文字(字母、數(shù)字、下劃線)。相當于 [A-Za-z0-9_]
|
\d |
數(shù)字。相當于 [0-9]
|
\s |
空白(任何空白字符,包括空格、制表符、換頁符等)。相當于 [ \f\n\r\t\v]
|
\W |
非文字 |
\D |
非數(shù)字 |
\S |
非空白 |
\f |
匹配一個換頁符 |
\n |
匹配一個換行符 |
\r |
匹配一個回車符 |
\t |
匹配一個制表符 |
\v |
匹配一個垂直制表符 |
\p |
匹配 CR/LF(等同于 \r\n),用來匹配 DOS 行終止符 |
標志
標志也叫模式修飾符,用來修改表達式的搜索結果,它們可以任意組合。
| 修飾符 | 描述 |
|---|---|
i |
忽略大小寫。 |
g |
全局匹配(查找所有匹配而非在找到第一個匹配后停止)。 |
m |
多行匹配:錨點元字符 ^ $ 工作范圍在每行的起始。 |
u |
Unicode 模式 |
y |
粘連(sticky),與 g 修飾符類似,也是全局匹配。y 修飾符確保匹配必須從剩余的第一個位置開始 |
s |
ES2018 引入 s 修飾符,使得 . 可以匹配任意單個字符。 dotAll 模式。即點(dot)代表一切字符。 |
忽略大小寫 (Case Insensitive)
修飾語 i 用于忽略大小寫。
'The fat cat sat on the mat.'.match(/The/gi) // ['The', 'the']
全局搜索 (Global search)
修飾符 g 常用于執(zhí)行一個全局搜索匹配,即(不僅僅返回第一個匹配的,而是返回全部)。
'The fat cat sat on the mat.'.match(/.(at)/g) // ['fat', 'cat', 'sat', 'mat']
多行修飾符 (Multiline)
多行修飾符 m 常用于執(zhí)行一個多行匹配。
像之前介紹的 (^,$) 用于檢查格式是否是在待檢測字符串的開頭或結尾。但我們如果想要它在每行的開頭和結尾生效,我們需要用到多行修飾符 m。
'The fat cat sat on the mat.'.match(/.at(.)?$/gm) // ['mat.']
零寬度斷言(前后預查)
先行斷言和后發(fā)斷言都屬于非捕獲簇(不捕獲文本 ,也不針對組合計進行計數(shù))。 先行斷言用于判斷所匹配的格式是否在另一個確定的格式之前,匹配結果不包含該確定格式(僅作為約束)。
例如,我們想要獲得所有跟在 $ 符號后的數(shù)字,我們可以使用正后發(fā)斷言 (?<=\$)[0-9\.]*。 這個表達式匹配 $ 開頭,之后跟著 0,1,2,3,4,5,6,7,8,9,. 這些字符可以出現(xiàn)大于等于 0 次。
'$'.match(/(?<=\$)[0-9\.]*/) // ['', index: 1, input: '$', groups: undefined]
'$1'.match(/(?<=\$)[0-9\.]*/) // ['1', index: 1, input: '$1', groups: undefined]
| 符號 | 描述 |
|---|---|
?= |
正先行斷言-存在 |
?! |
負先行斷言-排除 |
?<= |
正后發(fā)斷言-存在 |
?<! |
負后發(fā)斷言-排除 |
?= 正先行斷言
?= 正先行斷言,表示第一部分表達式之后必須跟著 ?=...定義的表達式。
返回結果只包含滿足匹配條件的第一部分表達式。 定義一個正先行斷言要使用 ()。在括號內部使用一個問號和等號: (?=...)。
正先行斷言的內容寫在括號中的等號后面。
'The fat cat sat on the mat.'.match(/(T|t)he(?=\sfat)/) // ['The', 'T', index: 0, input: 'The fat cat sat on the mat.', groups: undefined]
'The fat cat sat on the mat.'.match(/(T|t)he(?=\sfat)/) // ['The', 'T', index: 0, input: 'The fat cat sat on the mat.', groups: undefined]
?! 負先行斷言
?! 負先行斷言,用于篩選所有匹配結果,篩選條件為 其后不跟隨著斷言中定義的格式。 正先行斷言定義和負先行斷言一樣,區(qū)別就是 = 替換成 ! 也就是 (?!...)。
/(T|t)he(?!\sfat)/.exec('The fat cat sat on the mat.') // ['the', 't', index: 19, input: 'The fat cat sat on the mat.', groups: undefined]
?<= 正后發(fā)斷言
?<= 正后發(fā)斷言,用于篩選所有匹配結果,篩選條件為 其前跟隨著斷言中定義的格式。
/(?<=(T|t)he\s)(fat|mat)/.exec('The fat cat sat on the mat.') // ['fat', 'T', 'fat', index: 4, input: 'The fat cat sat on the mat.', groups: undefined]
?<! 負后發(fā)斷言
?<! 負后發(fā)斷言,用于篩選所有匹配結果,篩選條件為 其前不跟隨著斷言中定義的格式。
/(?<!(T|t)he\s)(cat)/.exec('The fat cat sat on the mat.') // ['cat', undefined, 'cat', index: 8, input: 'The fat cat sat on the mat.', groups: undefined]
貪婪匹配與惰性匹配(Greedy vs lazy matching)
正則表達式默認采用貪婪匹配模式,在該模式下意味著會匹配盡可能長的子串。我們可以使用 ? 將貪婪匹配模式轉化為惰性匹配模式。
-
*?:表示某個模式出現(xiàn) 0 次或多次,匹配時采用非貪婪模式。 -
+?:表示某個模式出現(xiàn) 1 次或多次,匹配時采用非貪婪模式。
'The fat cat sat on the mat.'.match(/(.*at)/) // ['The fat cat sat on the mat', 'The fat cat sat on the mat', index: 0, input: 'The fat cat sat on the mat.', groups: undefined]
'The fat cat sat on the mat.'.match(/(.*?at)/) // ['The fat', 'The fat', index: 0, input: 'The fat cat sat on the mat.', groups: undefined]
更多資料
- learn-regex
- regexr RegExr 是基于 HTML/JS 的工具,用于創(chuàng)建,測試和學習正則表達式。
- RegExper 可以將正則表達式轉成解釋圖片。
- RegExLib 收集各種常用的正則表達式,比如搜索 "email",會返回該站點收集的所有關于??正則表達式。
- RegexBuddy
- RegexMagic
- Rubular
- OWASP Validation Regex Repository
- CyrilEx Regex Tester
- 一份 PDF 備忘單(英文)