JavaScript 正則表達(dá)式(實(shí)例)

RegExp對象

字面量

var reg=/\bis\b/g;定義變量reg然后把正則表達(dá)式文本寫到兩個反斜杠之間,"\正則文本\"\b代表單詞邊界,\bis\b代表正則is單純后面再加個\b是保證is是一個完整的單詞,而不是兩個字符。

var reg=/\bis\b/;
"He is a boy .This is a dog.Where is she?".replace(reg,'IS');
//"He IS a boy .This is a dog.Where is she?"

發(fā)現(xiàn)就匹配了第一個單純is
我們使用g,也就是代表全文搜索匹配。var reg=/\bis\b/g;

var reg=/\bis\b/g;
"He is a boy .This is a dog.Where is she?".replace(reg,'IS');
//"He IS a boy .This IS a dog.Where IS she?"

構(gòu)造函數(shù)

var reg=new RegExp("\\bis\\b","g");使用new操作符來調(diào)用構(gòu)造函數(shù),構(gòu)造函數(shù)接收兩個參數(shù),第一個字符串里面是正則表達(dá)式的文本,這里有些特殊的地方就是反斜線寫了兩次,是因?yàn)镴avascript中反斜線本身就是特殊字符,如果我們想使用的話,就要進(jìn)行轉(zhuǎn)義,然后第二個參數(shù)是字符串,也是標(biāo)志g也就是代表全文搜索匹配

var reg=new RegExp("\\bis\\b","g");
"He is a boy .This is a dog.Where is she?".replace(reg,'IS');
//"He IS a boy .This IS a dog.Where IS she?"

修飾符

g:global全文搜索,不添加,搜索到第一個匹配停止

"He is a boy .This is a dog.Where is she?".replace(/\bis\b/g,'IS')
"He IS a boy .This IS a dog.Where IS she?"

i:ignore case 忽略大小寫,默認(rèn)大小寫敏感

"He Is a boy .This is a dog.Where is she?".replace(/\bis\b/gi,'hello')
"He hello a boy .This hello a dog.Where hello she?"

m:multiple lines 多行搜索

var mulSrt = "@123\n@321\n@876"
mulSrt
"@123
@321
@876 "
mulSrt.replace(/@\d/g, "G")
"G23
G21
G76 "
mulSrt.replace(/^@\d/g, "G")
"G23
@321
@876 "
mulSrt.replace(/^@\d/gm, "G")
"G23
G21
G76 "

元字符

正則表達(dá)式由兩種基本字符類型組成:

原義文本字符

原義文本字符意思就是代表它本來含義的字符比如/a/就是想匹配a

"jj abc a b c vf".replace(/a/gi,'hello')
//"jj hellobc hello b c vf"

/abc/就是想匹配abc

"jj abc a b c vf".replace(/abc/gi,'hello')
//"jj hello a b c vf"

這些都是原義文本字符。

元字符

元字符實(shí)在正則表達(dá)式中有特殊含義的非字母字符

比如\b它匹配的是單詞邊界,他的意思并不是匹配一個反斜線一個字母b,意思是匹配一個單詞邊界。這種就是特殊字符。

在正則表達(dá)式中有幾個字符需要注意他們都是有特殊含義的。

Paste_Image.png

字符類

我們工作時希望并不是匹配某個字符,而是希望匹配符合一系列特征abc

我們可以使用元字符[]來構(gòu)建一個簡單的類。
類就是符合某些特征的對象,是指一個泛指,而不是特指某個字符。
比如我們使用表達(dá)式[abc]就把a(bǔ)或者b或者c自定義成為一類,表達(dá)式就可以匹配這類的字符。他的意思是有它們一個就行。

"a1b2c3".replace(/[abc]/g,'x')
//"x1x2x3"

這樣我們發(fā)現(xiàn)abc對應(yīng)的地方都進(jìn)行替換了,

字符來取反

使用元字符^創(chuàng)建反向類/負(fù)向類
反向類的意思是不屬于某類的內(nèi)容
表達(dá)式[^abc]表示不是字符a或b或c的內(nèi)容

"a1b2c3".replace(/[^abc]/g,'x')
//"axbxcx"

把字符a或b或c以為外的字符替換成x了

范圍類

正則表達(dá)式提供了范圍類

我們可以使用[a-z]來鏈接兩個字符表示從a到z的任意字符
這是一個閉區(qū)間,也就是包含a和z本身

"a1b2c3x4z9".replace(/[a-z]/g,'Q');
//"Q1Q2Q3Q4Q9"

會發(fā)現(xiàn)a-z字母都被替換

[]組成的類內(nèi)部是可以連寫的[a-zA-Z]

"a1b2c3x4z9ASDFGGG".replace(/[a-zA-Z]/g,'Q');
"Q1Q2Q3Q4Q9QQQQQQQ"

匹配所有數(shù)字

"2016-11-12".replace(/[0-9]/g,'Q');
"QQQQ-QQ-QQ"

匹配所有數(shù)字和橫線

"2016-11-12".replace(/[0-9-]/g,'Q');
"QQQQQQQQQQ"

JS預(yù)定義類及邊界

正則表達(dá)式預(yù)定義類:

字符 含義
. 除了回車符和換行符之外的所有字符,等價于[^\r\n]
\d 數(shù)字字符,等價于[0-9] digit
\D 非數(shù)字字符,等價于[^0-9]
\s 空白符,等價于[\t\n\x0B\f\r] space
\S 非空白符,等價于[^\t\b\x0B\f\r]
\w 單詞字符(字母,數(shù)字,下劃線),等價于[a-zA-Z_0-9] word
\W 非單詞字符,等價于[^a-zA-Z_0-9]

例子:

匹配一個ab+數(shù)字+任意字符的字符串

/ab[0-9][^\r\n]/
"ab12334455sss".replace(/ab[0-9][^\r\n]/g,'Q');
//"Q334455sss"

或者

/ab\d.

"ab3klll".replace(/ab\d./g,"z")
//"zlll"

邊界

字符 含義
^ 以xxx開始
$ 以xxx結(jié)束
\b 單詞邊界
\B 非單詞邊界

\b單詞邊界

匹配字符

"This is a boy".replace(/is/g,'0')
//"Th0 0 a boy"

會發(fā)現(xiàn)所以 is都被替換

如果想替換單詞,單詞前后是有單詞邊界,所以要寫上邊界"This is a boy".replace(/\bis\b/g,'0')

"This is a boy".replace(/\bis\b/g,'0')
//"This 0 a boy"

\B非單詞邊界

如果想替換Thisis,觀察下特征,發(fā)現(xiàn)前面并不是邊界,后面是邊界那就這樣寫"This is a boy".replace(/\Bis\b/g,'0')

"This is a boy".replace(/\Bis\b/g,'0')
//"Th0 is a boy"

^以xxx為開始

"@123@abc@".replace(/@./g,'Q');
//"Q23Qbc@"

匹配全局@和任意字符

"@123@abc@".replace(/^@./g,'Q');
//"Q23@abc@"

以@和任意字符作為開始后面的不匹配

$以xxx為結(jié)束

"@123@abc@".replace(/.@/g,'Q');
//"@12QabQ"

匹配全局任意字符和@

"@123@abc@".replace(/.@$/g,'Q');
//"@123@abQ"

匹配最后一個任意字符和@

var mulSrt = "@123\n@321\n@876"
mulSrt
"@123
@321
@876 "
mulSrt.replace(/@\d/g, "G")
"G23
G21
G76 "
mulSrt.replace(/^@\d/g, "G")
"G23
@321
@876 "
mulSrt.replace(/^@\d/gm, "G")
"G23
G21
G76 "

量詞

字符 含義
出現(xiàn)零次或一次(最多出現(xiàn)一次)
+ 出現(xiàn)一次或多次(至少出現(xiàn)一次)
* 出現(xiàn)零次或多次(任意次)
{n} 出現(xiàn)n次
{n,m} 出現(xiàn)n到m次
{n,} 至少出現(xiàn)n次

我們希望匹配一個連續(xù)出現(xiàn)20次數(shù)字的字符串

/\d\d\d\d\d\d\d\d..../反斜杠加d表示數(shù)字表示數(shù)字出現(xiàn)20次把他寫20遍這樣非常麻煩如果出現(xiàn)100次那就要寫100遍嗎。為了解決這個問題正則表達(dá)式引入了量詞的概念。

"12341111133333333111111111111".replace(/\d{20}/g,"d")
//"d111111111"

匹配數(shù)字兩次

"1234".replace(/\d{2}/g,"d")
//"dd"

JS正則貪婪模式與非貪婪模式

貪婪模式

了解了量詞我們看這樣一個場景。

/\d{3,6}/

數(shù)字匹配3到6次,我們用12345678來執(zhí)行,我們寫的正則表達(dá)式是匹配數(shù)字3到6次,這個字符串中,即可以滿足3次4次5次6次,都是可以滿足的,那么正則表達(dá)式這時候該怎么處理?

正則表達(dá)式在處理的時候會盡可能多的匹配,直到匹配失敗。

"12345678".replace(/\d{3,6}/g,'A')
//"A78"

我們看到,他是匹配123456,78沒有匹配到,也就是說他是盡可能多的匹配而不是少的匹配。

這就是貪婪模式

非貪婪模式

讓正則表達(dá)式盡可能少的匹配,也就是說一旦匹配成功匹配不再繼續(xù)嘗試,就是非貪婪模式。

做法很簡單,在量詞后面加上?即可。

"12345678".replace(/\d{3,6}?/g,'A')
"AA78"

這個時候的執(zhí)行結(jié)果就是123,456后面兩個78沒有被匹配到。

分組

匹配字符串Byron連續(xù)出現(xiàn)3次的場景。

沒有接觸量詞的時候我們把這個單詞寫3遍,接觸量詞之后我們可能會這樣寫Byron{3}但是它代表的含義和我們預(yù)期的并不是一致的。實(shí)際上是n重復(fù)3次,前面不重復(fù),量詞是作為緊挨著它的字符,并不是整個單詞,否則怎么知道你匹配到哪。

"ByronByronByron".replace(/Byron{3}/g,'A')
//"ByronByronByron"
"ByronnnByronByron".replace(/Byron{3}/g,'A')
//"AByronByron"

那么如何讓他匹配整個單詞呢?或者是我們?nèi)Χǖ膬?nèi)容,那么就用到分組

使用()可以達(dá)到分組功能,使量詞作用于分組。

(Byron){3}這樣寫就能達(dá)到我們預(yù)期效果。整個單詞重復(fù)了3遍。

比如想匹配一個小寫字母加一個數(shù)字連續(xù)出現(xiàn)3次a1b2c3d4

`a1b2c3d4`.replace(/[a-z]\d{3}/g,"A")
//"a1b2c3d4"

這樣寫是匹配不到的,因?yàn)?code>\d{3}是找數(shù)字出現(xiàn)3次的場景。

我們將他分組即可

`a1b2c3d4`.replace(/([a-z]\d){3}/g,"A")
//"Ad4"

這樣就達(dá)到效果了。這樣量詞作用于整個分組。

使用|可以達(dá)到或的效果

"ByronCasper".replace(/Byron|Casper/g,"A");
//"AA"

這樣兩個都被匹配到了。

分組在或中的使用

"ByronsperByrCasper".replace(/Byr(on|Ca)sper/g,"A");
//"AA"

反向引用

比如我們想把2016-11-25變成11/25/2016

如果只是想把-替換成/是很簡單的

"2016-11-25".replace(/-/g,'/')
//"2016/11/25"

但是它順序也變了,

以往的寫法

"2016-11-25".replace(/\d{4}-\d{2}-\d{2}/g,'11/25/2016')
//"11/25/2016"

但是需要匹配的值變成了2016,月份可能變成11,我們想替換他本身,替換的內(nèi)容不再是一個常量,而是一個變量。這個時候該怎么處理?

我們用反向引用,

"2016-11-25".replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2/$3/$3')
"11/25/25"

我們用$引用分組內(nèi)內(nèi)容,我們對分組內(nèi)容進(jìn)行捕獲,捕獲后用$1$2$3來代替。

"2016-11-25".replace(/(\d{4})-(\d{2})-(\d{2})/g,'$1')
//"2016"
 "2016-11-25".replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2')
//"11"
 "2016-11-25".replace(/(\d{4})-(\d{2})-(\d{2})/g,'$3')
//"25"

"2016-11-25".replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2/$3/$3')
"11/25/25"

忽略分組

不希望捕獲某些分組,只需要在分組內(nèi)加上?:就可以。

"abcaok".replace(/(abc).(ok)/g,'$1/$2')
//"abc/ok"

"abcaok".replace(/(?:abc).(ok)/g,'$1/$2')
//"ok/$2"

前瞻

正則表達(dá)式的前瞻:

  1. 正則表達(dá)式從文本頭部向尾部開始解析,文本尾部方向,成為“前”
  2. 前瞻 就是在正則表達(dá)式匹配到規(guī)則的時候,向前檢查是否符合斷言。比如找到兒子為張三,還得看看他的父親是否是李四
    后顧/后瞻方向相反

注意:JavaScript不支持后顧

匹配單詞數(shù)字加數(shù)字

"a2*3".replace(/\w(\d)/g,"A");
//"A*3"

匹配單詞數(shù)字,注:這個單詞數(shù)字后面必須有數(shù)字才會匹配,(?=\d)不能算在匹配內(nèi)容,這是斷言。

"a2*3".replace(/\w(?=\d)/g,"A");
//"A2*3"

寫個復(fù)雜點(diǎn)的案例

"a2*34v8".replace(/\w(?=\d)/g,"A");
//"A2*A4A8"

a2*34``v8這三個符合要求

"a2*34vv".replace(/\w(?=\d)/g,"A");
//"A2*A4vv"

a2*34vv,這里只有兩個匹配vvv是對的但是它后面不是數(shù)字,所以不成功。

現(xiàn)在改一下比配后面不是數(shù)字的

"a2*34vv".replace(/\w(?!\d)/g,"A");
"aA*3AAA"

a2*``34``vv,2變成A。4vv都符合所以是AAA

js對象屬性

描述 默認(rèn)
g:global是否全文搜索 默認(rèn)false
i:ignore case是否大小寫敏感 默認(rèn)false
m:multiline多行搜索 默認(rèn)值false
lastIndex:當(dāng)前正則表達(dá)式匹配內(nèi)容的最后一個字符的下一個位置(即下一次匹配開始的位置)。
source : 正則表達(dá)式的文本字符串。

test 和 exec方法

正則表達(dá)式本身的兩個方法
1.test
RegExp.prototype.test(str)

用于測試字符串參數(shù)中是否存在匹配正則表達(dá)式模式的字符串

如果存在則返回true,否則返回false

lastIndex 記錄當(dāng)前匹配結(jié)果的、最后一個字符的、下一個字符的位置
注意:test()方法在匹配的時候當(dāng)匹配到一個結(jié)果時,會從lastIndex位置開始匹配下一個結(jié)果,直到不存在的時候才置為0。因此,當(dāng)使用全局g屬性標(biāo)識時,當(dāng)匹配到最后一個結(jié)果時,lastIndex值指向不存在的位置,此時再執(zhí)行test()會返回false。
例子:多次執(zhí)行test()方法,會在true、false之間循環(huán)
(/\w/g).test('a')每次執(zhí)行都是正確的,但是通過實(shí)例化對象,需要很大的開銷
test()方法:原意就是測試有沒有、能不能匹配上,當(dāng)使用test原意時,沒必要加g

2.exec

RegExp.prototype.exec(str)
使用正則表達(dá)式模式對字符串執(zhí)行搜索,并將更新全局RegExp對象的屬性一反映匹配結(jié)果
如果沒有匹配的文本則返回 null,否則返回一個結(jié)果數(shù)組:

  • index 聲明匹配文本的第一個字符位置
  • input 存放被檢索的字符串 string

非全局調(diào)用
調(diào)用非全局的RegExp對象的 exec()時,返回數(shù)組
第一個元素是與正則表達(dá)式相匹配的文本
第二個元素是與RegExpObject的第一個子表達(dá)式相匹配的文本(如果有的話)
第三個元素是與RegExp對象的第二個子表達(dá)式相匹配的文本(如果有的話),以此類推

字符串對象方法

String.prototype.search(reg)

search() 方法用于檢索字符串中指定的子字符串,或檢索與正則表達(dá)式相匹配的子字符串。

語法

stringObject.search(regexp)
參數(shù) 描述
regexp 該參數(shù)可以是需要在 stringObject 中檢索的子串,也可以是需要檢索的 RegExp 對象。注釋:要執(zhí)行忽略大小寫的檢索,請追加標(biāo)志 i。

返回值

stringObject 中第一個與 regexp 相匹配的子串的起始位置。

注釋:如果沒有找到任何匹配的子串,則返回 -1。

說明

search() 方法不執(zhí)行全局匹配,它將忽略標(biāo)志 g。它同時忽略 regexp 的 lastIndex 屬性,并且總是從字符串的開始進(jìn)行檢索,這意味著它總是返回 stringObject 的第一個匹配的位置。

"a1b1c1d1".search('1')
//1
"a1b1c1d1".search('10')
//-1
"a1b1c1d1".search(1)
//1
"a1b1c1d1".search(/1/)
//1

String.prototype.match(reg)

match() 方法可在字符串內(nèi)檢索指定的值,或找到一個或多個正則表達(dá)式的匹配。

該方法類似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。

參數(shù) 描述
searchvalue 必需。規(guī)定要檢索的字符串值。
regexp 必需。規(guī)定要匹配的模式的 RegExp 對象。如果該參數(shù)不是 RegExp 對象,則需要首先把它傳遞給 RegExp 構(gòu)造函數(shù),將其轉(zhuǎn)換為 RegExp 對象。

返回值

存放匹配結(jié)果的數(shù)組。該數(shù)組的內(nèi)容依賴于 regexp 是否具有全局標(biāo)志 g。

說明

match() 方法將檢索字符串 stringObject,以找到一個或多個與 regexp 匹配的文本。這個方法的行為在很大程度上有賴于 regexp 是否具有標(biāo)志 g。

如果 regexp 沒有標(biāo)志 g,那么 match() 方法就只能在 stringObject
中執(zhí)行一次匹配。如果沒有找到任何匹配的文本, match() 將返回
null。否則,它將返回一個數(shù)組,其中存放了與它找到的匹配文本有關(guān)的信息。該數(shù)組的第 0
個元素存放的是匹配文本,而其余的元素存放的是與正則表達(dá)式的子表達(dá)式匹配的文本。除了這些常規(guī)的數(shù)組元素之外,返回的數(shù)組還含有兩個對象屬性。index
屬性聲明的是匹配文本的起始字符在 stringObject 中的位置,input 屬性聲明的是對 stringObject 的引用。

如果 regexp 具有標(biāo)志 g,則 match() 方法將執(zhí)行全局檢索,找到 stringObject
中的所有匹配子字符串。若沒有找到任何匹配的子串,則返回
null。如果找到了一個或多個匹配子串,則返回一個數(shù)組。不過全局匹配返回的數(shù)組的內(nèi)容與前者大不相同,它的數(shù)組元素中存放的是
stringObject 中所有的匹配子串,而且也沒有 index 屬性或 input 屬性。

注意:在全局檢索模式下,match() 即不提供與子表達(dá)式匹配的文本的信息,也不聲明每個匹配子串的位置。如果您需要這些全局檢索的信息,可以使用 RegExp.exec()。

var str="Hello world!"
document.write(str.match("world") + "<br />")
document.write(str.match("World") + "<br />")
document.write(str.match("worlld") + "<br />")
document.write(str.match("world!"))

輸出

world
null
null
world! 

正則方法非全局匹配

var reg3 = /\d(\w)/;
var reg4 = /\d(\w)/g;
var ts = '$1a2b3c4d5e';

var ret = ts.match(reg3);
console.log(ret);    //["1a", "a", index: 1, input: "$1a2b3c4d5e"]
document.write(ret);  //1a,a

正則方法全局匹配

var reg3 = /\d(\w)/;
var reg4 = /\d(\w)/g;
var ts = '$1a2b3c4d5e';

var ret = ts.match(reg4);
console.log(ret);   //["1a", "2b", "3c", "4d", "5e"]
document.write(ret);//1a,2b,3c,4d,5e

String.prototype.match(reg)方法

split() 方法用于把一個字符串分割成字符串?dāng)?shù)組。

基本用法

var op = 'a,b,c,d';
var spo = op.split(',');
console.log(spo);
//["a", "b", "c", "d"]

在一些復(fù)雜分割情況下可以用正則用法

var op = 'a1b2c3d';
var spo = op.split(/\d/);
console.log(spo);
//["a", "b", "c", "d"]

再復(fù)雜

var op = 'a,b|c?d';
var spo = op.split(/[,|\|\?]/g);
console.log(spo);
//["a", "b", "c", "d"]

String.prototype.replace方法

傳入兩個參數(shù)replace(找誰,替換誰)

"a1b".replace(/1/,2)
//"a2b"


"a1b1c1".replace(/1/g,2)
//"a2b2c2"

"a1b1c1".replace(/\d/g,2)
"a2b2c2"

如果我想把"a1b2c3d4" => "a2b3c4d5"該怎么實(shí)現(xiàn)呢?

var h = "a1b2c3d4".replace(/\d/g, function(match, index, origin) {
    //console.log(index);
    return parseInt(match) + 1;
});
console.log(h);//a2b3c4d5



var h = "a1b2c3d4e5".replace(/(\d)(\w)(\d)/g, function(match, g1, g2, g3, index, origin) {
    //console.log(index);
    return g1 + g3;
});
console.log(h);//a12c34e5
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容