常用
作用:找到有規(guī)則的文本
// 常用
. // 表示任意字符,不包括回車
\n // 回車
\d // 表示數(shù)字
\b // boundary 邊界線,跟空格無(wú)關(guān),而是詞組的組成形式,英語(yǔ)是空格,中文是單字
{n} // n填數(shù)字,匹配前面的多個(gè)
\w // word,匹配字母數(shù)字或者下劃線
\s // space 匹配空白符
+ // 前面的字符一個(gè)或多個(gè)
^ // 開(kāi)頭
$ // 結(jié)尾
$1 // 需要放在替換欄,表示匹配到的字符保存下來(lái),$1,$2… 對(duì)應(yīng)前邊第n個(gè)()包裹的東西
// 嵌套時(shí)從左到右看括號(hào)
? // 可有可無(wú) -?\d+ 表示可有負(fù)號(hào)或者可以沒(méi)有
[ab] // a或b
\t //水平制表符
\v //垂直制表符
\n //換行符
\r // 回車符
\0 // 空字符
\f // 換頁(yè)符
\cX // 與X對(duì)應(yīng)的控制字符(Ctrl+x)
修飾符
- g : global 全局搜索
- i : ignore case 忽略大小寫
- m : multiple lines 多行搜索
默認(rèn)下大小寫敏感,且只匹配第一個(gè)匹配到的
元字符
* + ? ^ . | \ () {} []
范圍類
表示一類,其中有一個(gè)即匹配,泛指某個(gè)特征的對(duì)象
[a-z] 表示所有小寫字母
[a-zA-Z] 表示所有字母
[abc] 表示abc歸為一類,有其中一個(gè)
^負(fù)向類,字符類取反
[^abc] 不包含a或b或c
預(yù)定義類
字符 | 等價(jià)類 | 含義 |
---|---|---|
. | [^\r\n] | 除了回車符和換行符之外的所有字符 |
\d | [0-9] | 數(shù)字字符 |
\s | [\t\n\xOB\f\r] | 空白符 space |
\S | [^\t\n\xOB\f\r] | 非空白符 |
\w | [a-zA-z_0-9] | 單詞字符(字母\數(shù)字\下劃線) |
\W | [^a-zA-z_0-9] | 非單詞字符 |
\b | 單詞邊界 | |
\B | 非單詞邊界 | |
^ | 以xxx開(kāi)始 判斷依據(jù)是前面是否為空白符 | |
$ | 以xxx主動(dòng)放棄 |
量詞
字符 | 含義 |
---|---|
? | 出現(xiàn)0次或1次(最多一次) |
+ | 出現(xiàn)1次或者多次(至少一次) |
* | 出現(xiàn)0次或者多次(任意次) |
{n} | 出現(xiàn)n次 |
{n,m} | 出現(xiàn)n到m次 |
{n,} | 至少出現(xiàn)n次 |
貪婪匹配&懶惰匹配模式
默認(rèn)為貪婪模式,指有重復(fù)限定符時(shí),匹配盡可能多的字符
限定符后使用?
則使用懶惰匹配
懶惰匹配限定符
代碼/語(yǔ)法 | 說(shuō)明 |
---|---|
*? | 重復(fù)任意次,但盡可能少重復(fù) |
+? | 重復(fù)1次或更多次任斋,但盡可能少重復(fù) |
?? | 重復(fù)0次或1次第美,但盡可能少重復(fù) |
{n,m}? | 重復(fù)n到m次素标,但盡可能少重復(fù) |
{n,}? | 重復(fù)n次以上俩由,但盡可能少重復(fù) |
栗子
貪婪模式
'123456789'.replace(/\d{3,6}/,'x')
// 'xxxxxx789'
非貪婪模式下,會(huì)往最少的匹配
'123456789'.match(/\d{3,6}?/g)
// ['123','456','789']
捕獲(分組)
// 自動(dòng)命名分組
(abc){3} 使量詞作用域分組
// 分組命名
(?<name>exp)
(?'name'exp) 命名為name的分組
// 不捕獲(忽略分組)
(?:abc).(ok) // abc分組被忽略
// 反向引用
'2015-12-25'.replace(/(\d{4})-(\d{2})-(\d{2})/,'$2/$1/$3')
// 輸出"12/25/2015"
// 引用命名
\k<name>
(?<abc>\d+)_\k<abc>\w+
// 可以在同一個(gè)正則里面用,在JavaScript RegExp對(duì)象方法.replace兩個(gè)參數(shù)里也可以使用用于替換
零寬斷言 (Lookahead and Lookbehind Zero-Length Assertions)
- 前瞻即匹配到規(guī)則,向前看(方向從文本末尾向開(kāi)頭稱為前)檢查是否符合斷言
- 后顧/后瞻則相反
- 正向(正預(yù)測(cè)/正回顧)指條件語(yǔ)句匹配
- 負(fù)向相反
需注意JavaScript不支持后顧
名稱 | 正則 | 含義 |
---|---|---|
正預(yù)測(cè)先行斷言(正向前瞻) | assert(?=exp) | assert后面必須匹配exp條件 |
負(fù)預(yù)測(cè)先行斷言(負(fù)向前瞻) | assert(?!exp) | assert后面不能匹配exp條件 |
正回顧后發(fā)斷言(正向后顧) | assert(?<=exp) | JavaScript不支持 |
負(fù)回顧后發(fā)斷言(負(fù)向后顧) | assert(?<!exp) | JavaScript不支持 |
JavaScript中構(gòu)建方式 RegExp 對(duì)象
字面量
/\b\w/g
// 斜杠之間為正則對(duì)象 斜杠右邊為修飾符
構(gòu)造函數(shù)
var reg = new RegExp('\\b\\w','g')
// 兩個(gè)參數(shù) 第一參數(shù)注意轉(zhuǎn)義
對(duì)象屬性
ignoreCase:返回一個(gè)布爾值苦银,表示是否設(shè)置了i修飾符莹妒,該屬性只讀。
global:返回一個(gè)布爾值舞吭,表示是否設(shè)置了g修飾符泡垃,該屬性只讀。
multiline:返回一個(gè)布爾值羡鸥,表示是否設(shè)置了m修飾符蔑穴,該屬性只讀。
lastIndex:返回下一次開(kāi)始搜索的位置惧浴。該屬性可讀寫存和,但是只在設(shè)置了g修飾符時(shí)有意義。
source:返回正則表達(dá)式的字符串形式(不包括反斜杠)衷旅,該屬性只讀捐腿。
var reg = /abc/igm;
reg.gloabl // true 返回是否搜索全文
reg.ignoreCase // true 返回是否大小寫忽略
reg.multiline // true 返回是否多行匹配
reg.lastIndex // 0 返回索引位置
reg.source // "abc" 返回正則表達(dá)式字符串形式
對(duì)象方法
RegExp.prototype.test()
返回一個(gè)布爾值,表示是否匹配
/apple/.test('牛頓吃蘋果') // false
如果帶g
修飾符,則每一次test()
都從上一次結(jié)束的位置開(kāi)始向后匹配
var reg = /a/g
var string = "apple & apple"
reg.lastIndex // 0
reg.test(string) // true 匹配到第一個(gè)a
reg.lastIndex // 1 位置是第一個(gè)
reg.test(string) // true 匹配到第二個(gè)a
reg.lastIndex // 9 位置是第9個(gè)開(kāi)始
reg.test(string) // false 匹配不到
reg.lastIndex // 0 匹配不到了
reg.test(string) // true 重新匹配到第一個(gè)
reg.lastIndex // 1 位置是第一個(gè)
RegExp.prototype.exec(str)
使用正則表達(dá)式模式對(duì)字符串進(jìn)行搜索,并更新對(duì)象實(shí)例的屬性,返回匹配結(jié)果。如果發(fā)現(xiàn)匹配柿顶,就返回一個(gè)數(shù)組茄袖,成員是每一個(gè)匹配成功的子字符串,否則返回null九串。
var s = 'cat'
var r1 = /a/
var r2 = /b/
r1.exec(s) // ["a"]
r2.exec(s) // null
如果正則表示式包含圓括號(hào)()
(即含有“組匹配”)绞佩,則返回的數(shù)組會(huì)包括多個(gè)成員寺鸥。第一個(gè)成員是整個(gè)匹配成功的結(jié)果猪钮,后面的成員就是圓括號(hào)對(duì)應(yīng)的匹配成功的組品山。也就是說(shuō),第二個(gè)成員對(duì)應(yīng)第一個(gè)括號(hào)烤低,第三個(gè)成員對(duì)應(yīng)第二個(gè)括號(hào)肘交,以此類推。整個(gè)數(shù)組的length屬性等于組匹配的數(shù)量再加1扑馁。
var s = '_x_x';
var r = /_(x)/;
r.exec(s) // ["_x", "x"]
上面代碼的exec()
方法涯呻,返回一個(gè)數(shù)組。第一個(gè)成員是整個(gè)匹配的結(jié)果腻要,第二個(gè)成員是圓括號(hào)匹配的結(jié)果,如果還有則繼續(xù)匹配并返回到數(shù)組內(nèi)
同時(shí)該數(shù)組還包含兩個(gè)屬性,需要注意這個(gè)與正則實(shí)例對(duì)象的屬性不同
index
匹配成功的開(kāi)始位置,從0開(kāi)始計(jì)算
input
整個(gè)遠(yuǎn)字符串
var r = /a(p+)/
var arr = r.exec('_apple pine apple') // 是返回的數(shù)組才有屬性
arr // ["app","pp"]
arr.index // 1 位置是第二個(gè)
arr.input // "_apple pine apple"
如果使用修飾符g
,下一次搜索會(huì)從上次成功匹配結(jié)束的位置開(kāi)始
var r = /a(p+)/g
var s = 'apple pine pine apple pine'
var a1 = r.exec(s)
a1 //["app","pp"]
a1.index // 0
r.lastIndex // 3
var a2 = r.exec(s)
a2 //["app","pp"]
a2.index // 16
r.lastIndex // 19
// 如果匹配不到了
var a3 = r.exec(s)
a3 // null
a3.index // TypeError: Cannot read property 'index' of null
r.lastIndex // 0
// 循環(huán)了
var a4 = r.exec(s)
a4 //["app","pp"]
a4.index // 0
r.lastIndex // 3
由于其存在循環(huán)的情況,我們利用返回的數(shù)組判斷循環(huán)結(jié)束,一次循環(huán)完成所有匹配
var r = /a(b+)a/g;
var s = '_abbba_aba_';
while(true) {
var match = r.exec(s);
if (!match) break; //當(dāng)數(shù)組結(jié)果不存在時(shí)就跳出循環(huán)
console.log(match[1]);
}
// bbb
// b
如果設(shè)置了lastIndex
屬性,就會(huì)從lastIndex
位置開(kāi)始匹配,需要g
修飾符才生效
var r1 = /a(p+)/
r1.lastIndex = 5
var a1 = r1.exec('apple pine apple')
a1.index // 0
r1.lastIndex // 3
// 由于沒(méi)有g(shù) 所以無(wú)效
var r2 = /a(p+)/g
r2.lastIndex = 5
var a2 = r2.exec('apple pine apple')
a2.index // 11
r2.lastIndex // 14
// 有g(shù)修飾符,所以生效
字符串對(duì)象方法 search()
| match()
| replace()
| split()
search()
返回匹配結(jié)果的在字符串中的位置,g
修飾符無(wú)效,因此lastIndex屬性也無(wú)效
'apple pine apple'.search(/a(p+)/)
// 0
// 第一個(gè)位置,從0 開(kāi)始數(shù)
'apple pine apple'.search(/bba/)
// -1
// 沒(méi)匹配到
var r = /a(p+)/g;
r.lastIndex = 5; // 無(wú)效
'apple pine apple'.search(r) // 0
match()
返回匹配成功的的結(jié)果的數(shù)組,失敗則返回null
,g
無(wú)效
var s = 'apple pine'
s.match(/a(p+)/) // ["app", "pp"]
s.match(/b(a+)/) // null
var r = /a(p+)/g
r.lastIndex = 5
s.match(r) // ["app", "pp"]
r.lastIndex // 0
// g修飾符無(wú)效
replace()
接受兩個(gè)參數(shù),第一個(gè)為搜索模式,第二個(gè)為替換內(nèi)容,有g
修飾符時(shí)替換所有字符
var s = 'apple'
s.replace(/p/,'b') // "abple"
s.replace(/p/g,'b') // "abble"
// 清除字符串兩端空白符
var str = ' #id div.class ';
str.replace(/^\s+|\s+$/g, '')
// "#id div.class"
replace()
方法的第二個(gè)參數(shù)可以使用美元符號(hào)$复罐,用來(lái)指代所替換的內(nèi)容
$& 指代匹配的子字符串。
$` 指代匹配結(jié)果前面的文本雄家。
$' 指代匹配結(jié)果后面的文本效诅。
$n 指代匹配成功的第n組內(nèi)容,n是從1開(kāi)始的自然數(shù)趟济。
$$ 指代美元符號(hào)$乱投。
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// "world hello"
'abc'.replace('b', '[$`-$&-$\']')
// "a[a-b-c]c"
第二個(gè)參數(shù)還可以是函數(shù),將匹配內(nèi)容替換為函數(shù)返回值
該函數(shù)可接受多個(gè)參數(shù),第一個(gè)為捕捉的內(nèi)容match
,第二個(gè)為第二個(gè)參數(shù)是捕捉到的組匹配(有多少個(gè)組匹配,就有多少個(gè)對(duì)應(yīng)的參數(shù))顷编。此外戚炫,最后還可以添加兩個(gè)參數(shù),倒數(shù)第二個(gè)參數(shù)是捕捉到的內(nèi)容在整個(gè)字符串中的位置(比如從第五個(gè)位置開(kāi)始)媳纬,最后一個(gè)參數(shù)是原字符串双肤。
var prices = {
'pr_1': '$1.99',
'pr_2': '$9.99',
'pr_3': '$5.00'
};
var template = '/* ... */'; // 這里可以放網(wǎng)頁(yè)模塊字符串
template.replace(
/(<span id=")(.*?)(">)(<\/span>)/g,
function(match, $1, $2, $3, $4){
return $1 + $2 + $3 + prices[$2] + $4;
}
);
split()
字符串對(duì)象按正則規(guī)則分割,返回分割后組成的數(shù)組,接受兩個(gè)參數(shù),第一個(gè)為分割規(guī)則,第二個(gè)為最大成員數(shù)
// 非正則分隔
'a, b,c, d'.split(',')
// [ 'a', ' b', 'c', ' d' ]
// 正則分隔,去除多余的空格
'a, b,c, d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]
// 指定返回?cái)?shù)組的最大成員
'a, b,c, d'.split(/, */, 2)
[ 'a', 'b' ]
// 組匹配成員也會(huì)返回到數(shù)組
'aaa*a*'.split(/(a*)/)
// [ '', 'aaa', '*', 'a', '*' ]
參考:
http://javascript.ruanyifeng.com/stdlib/regexp.html
https://regexper.com/
http://www.regular-expressions.info/lookaround.html