摘要:表示進(jìn)行多行匹配。如果正則表達(dá)式中含有子表達(dá)式,那么該數(shù)組后續(xù)的項(xiàng)依次為匹配到的第一個(gè)子表達(dá)式的匹配結(jié)果,第二個(gè)第個(gè)。關(guān)于正則方法有一點(diǎn)必須要提,很容易導(dǎo)致錯(cuò)誤的情況。這時(shí)候直接使用該正則表達(dá)式對(duì)進(jìn)行方法調(diào)用,卻返回了。匹配前一項(xiàng)至少次。
有人說,一行正則抵得上100行代碼……
正則表達(dá)式,每門語言都有,在我們的js開發(fā)中,最常見的使用場(chǎng)景:一是表單驗(yàn)證,像是登錄注冊(cè)啊,用戶輸入檢測(cè)啊,不管在前臺(tái)項(xiàng)目還是后臺(tái)管理系統(tǒng),都會(huì)經(jīng)常使用;二是,在開發(fā)一些重?cái)?shù)據(jù)交互的后臺(tái)管理系統(tǒng)或者應(yīng)用的時(shí)候,更是會(huì)大量的使用,各種字符匹配,表達(dá)式檢測(cè)等等。
正則本身知識(shí)點(diǎn)不是很多,但是由于各種字符意思容易忘記,所以需要經(jīng)常復(fù)習(xí),多使用就記住了。
創(chuàng)建一個(gè)正則表達(dá)式:// 通過RegExp構(gòu)造函數(shù)創(chuàng)建
var regex1 = new RegExp("[a-z]", "g");
// 通過直接字面量創(chuàng)建
var regex2 = /[a-z]/g;
這兩種方式都可以創(chuàng)建正則表達(dá)式,以上兩種方式創(chuàng)建了一個(gè)等價(jià)的正則表達(dá)式,均為匹配字母a到z。但是日常開發(fā)中,基本都是通過直接字面量創(chuàng)建:兩個(gè)反斜杠之間為正則表達(dá)式,反斜杠后面跟著修飾符i、g、m。修飾符可寫可不寫,也可以同時(shí)寫多個(gè),他們的意思分別是:
i:表示忽略大小寫,就是在字符串匹配的時(shí)候不區(qū)分大小寫。var str = "hello world
my name is LengChui."
可看到這個(gè)字符串中有一個(gè) 換行符,正常匹配時(shí),到 就結(jié)束了,也就是只會(huì)匹配到這一行的結(jié)尾。但是如果加了m修飾符,會(huì)繼續(xù)往后面匹配,一直匹配到字符串的最終結(jié)尾。
當(dāng)然了,修飾符可以同時(shí)寫多個(gè),例如:var regex = /[a-z]/ig;表示匹配所有的字母a到z,且不區(qū)分大小寫。這樣,對(duì)于字符串"a123H"就會(huì)匹配到a和Z
所有的正則表達(dá)式都有test和exec這兩個(gè)方法。
test()方法:測(cè)試字符串中是否包含了匹配該正則表達(dá)式的子串,如果包含了這樣的子串,那么返回true,否則返回false
// 定義一個(gè)匹配hello字符串的正則表達(dá)式
var reg = /hello/g;
var str = "hello world";
// 如果字符串str中匹配到了hello字符串,則打印如下信息
if (reg.test(str)) {
console.log("字符串str中含有hello子串")
}
這個(gè)方法相信在驗(yàn)證用戶輸入內(nèi)容的時(shí)候,會(huì)經(jīng)常使用到。例如,相信很多人寫過類似下面的正則驗(yàn)證用戶輸入值的合法性代碼:
// 點(diǎn)擊提交按鈕,驗(yàn)證輸入值,提交ajax請(qǐng)求
document.getElementById("submitButton").addEventListener("click", function (event) {
// 獲取用戶輸入的手機(jī)號(hào)
var phoneNumber = document.getElementById("phone");
// 驗(yàn)證手機(jī)號(hào)格式的正則
var regPhone = /^1[3|4|5|8]d{9}$/g;
// 檢測(cè)輸入的合法性,進(jìn)行錯(cuò)誤提示
if (!phoneNumber) {
$tim("請(qǐng)輸入手機(jī)號(hào)!")
return;
}
if (!regPhone.test(phoneNumber)) {
$tip("手機(jī)號(hào)格式不正確,請(qǐng)重新輸入!");
return;
}
// 如果驗(yàn)證成功,提交ajax請(qǐng)求
$.ajax(………………)
}, false);
exec方法:接收一個(gè)參數(shù),即待檢測(cè)的字符串。它返回一個(gè)增強(qiáng)的數(shù)組對(duì)象,數(shù)組的第一項(xiàng)為匹配到的字符串。如果正則表達(dá)式中含有子表達(dá)式,那么該數(shù)組后續(xù)的項(xiàng)依次為匹配到的第一個(gè)子表達(dá)式的匹配結(jié)果,第二個(gè)……第n個(gè)。如果沒有匹配到任何內(nèi)容,則返回null。
通過例子來說明exec的使用方法:
// 定義一個(gè)字符串
var str = "hello javascript, hello javaspring"
// 定義一個(gè)正則表達(dá)式,該表達(dá)式匹配任意java后跟任意大小寫字母的字符串
// 注意這里的正則表達(dá)式?jīng)]有加g,后面會(huì)說明exec的正則表達(dá)式加g與不加g的區(qū)別
var reg = /java([a-zA-Z]+)/;
// 調(diào)用exec方法
var execResult = reg.exec(str);
console.log(execResult)
看下最終的打印結(jié)果:
可以看到返回一個(gè)數(shù)組,數(shù)組的第一項(xiàng)為匹配到的結(jié)果,第二項(xiàng)為第一個(gè)子表達(dá)式的匹配結(jié)果,如果還有其他子表達(dá)式,會(huì)依次往后排。同時(shí)這個(gè)數(shù)組對(duì)象還有以下幾個(gè)屬性:
groups: undefined
index// 當(dāng)前匹配結(jié)果的開始下標(biāo)。這里匹配的javascript字符串的開始下標(biāo)為6。
input // 待匹配的字符串,其實(shí)就是我們的這里的str字符串
注意上述正則表達(dá)式/java([a-zA-Z]+)/沒有加修飾符g,這意味著不需要全局匹配。這種情況下,exec()方法只會(huì)匹配依次便最終匹配結(jié)束了,那么如果繼續(xù)調(diào)用execResult = reg.exec(str);,則會(huì)重新開始匹配,即從字符串0的位置開始重新匹配并返回新的匹配結(jié)果。其結(jié)果肯定是一樣的。如下面例子:
var str = "hello javascript, hello javaspring"
var reg = /java([a-zA-Z]+)/;
// 第一次匹配調(diào)用并打印結(jié)果
var execResult = reg.exec(str);
console.log(execResult);
// 重新調(diào)用并打印結(jié)果
execResult = reg.exec(str);
console.log(execResult);
可以看到兩次調(diào)用的匹配結(jié)果是一樣的。這里不禁就有人說了,那不是廢話了,調(diào)用同一個(gè)表達(dá)式,結(jié)果不就一樣嘛。然而,還真不是。在介紹這個(gè)之前,我們先簡(jiǎn)單提一下正則表達(dá)式的實(shí)例屬性,告訴了我們?cè)撜齽t表達(dá)式的一些基本信息。這個(gè)不需要記,了解一下即可:
var reg2 = /a/igm; // 定義一個(gè)不區(qū)分大小寫、全局匹配、多行匹配字符串a(chǎn)的正則表達(dá)式 console.dir(reg2) // 打印出該對(duì)象
下表中列出了所有的正則表達(dá)式實(shí)例屬性。
實(shí)例屬性 | 含義 |
global | Boolean值,指明正則表達(dá)式是否包含g修飾符 |
ignoreCase | Boolean值,指明正則表達(dá)式是否包含i修飾符 |
lastIndex | 若正則表達(dá)式包含g修飾符,該屬性指明執(zhí)行exec()或test()方法后,最后一次匹配結(jié)果字符串后面的第一個(gè)字符的位置 |
source | 只讀屬性,給出了正則表達(dá)式的內(nèi)容,即除了斜杠和選項(xiàng)字符之外的整個(gè)正則表達(dá)式。 |
multiline | Boolean值,指定搜索字符串時(shí)是否跨行搜索,即是否包含m修飾符,該屬性的另外一個(gè)名稱是$* |
了解了這個(gè)之后,我們回過頭來繼續(xù)說exec()方法。在調(diào)用exec()方法的正則表達(dá)式?jīng)]有加修飾符g,即不是全局匹配的模式下,每次調(diào)用exec()之后,本次的正則匹配也就最終結(jié)束了,注意是最終結(jié)束了。下次該正則表達(dá)式再次調(diào)用exec()方法時(shí)會(huì)從字符串開頭開始匹配,可以立即為開始了一次新的正則匹配。
那么如果調(diào)用exec()方法的正則表達(dá)式是全局匹配的話(加了修飾符g),該正則表達(dá)式每次調(diào)用exec()方法結(jié)束后,其實(shí)例屬性lastIndex都會(huì)指向本次匹配結(jié)果字符串后面一個(gè)字符的位置,直到匹配結(jié)果返回null,即沒有匹配到任何結(jié)果的時(shí)候,才會(huì)將其lastIndex屬性重置為0。繼續(xù)看這個(gè)例子演示:
var str = "hello javascript, hello javaspring"
// 定義匹配任何java后跟任意大小寫字母的字符串,注意這里是全局匹配
var reg = /java([a-zA-Z]+)/g;
// 該正則表達(dá)式第一次調(diào)用exec()方法并打印匹配結(jié)果和其實(shí)例屬性lastIndex
var execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);
// 第二次調(diào)用
execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);
// 第三次調(diào)用
execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);
從打印結(jié)果可以看出,第一次匹配到了字符串javascript,其開始下標(biāo)為6,實(shí)例屬性lastIndex為16,即javascript字符串后面的一個(gè)字符“逗號(hào)”的位置下標(biāo)。第二次調(diào)用的匹配結(jié)果為javaspring,lastIndex的值為34。第三次調(diào)用沒有匹配到任何結(jié)果,所以返回了null,其lastIndex的結(jié)果也被重置為了0。
關(guān)于正則方法exec()有一點(diǎn)必須要提,很容易導(dǎo)致錯(cuò)誤的情況。當(dāng)調(diào)用exec()方法的正則表達(dá)式是全局匹配的情況下,對(duì)一個(gè)字符串匹配后,如果沒有匹配到最終結(jié)果,即沒有返回null的情況下,使用該正則表達(dá)式對(duì)新字符串進(jìn)行exec()方法調(diào)用時(shí),切記一定要先將該正則表達(dá)式的實(shí)例屬性lastIndex重置為0。看例子:
var str = "hello javascript, hello javaspring"
var str2 = "javascript and html"
// 定義匹配任何java后跟任意大小寫字母的正則表達(dá)式,全局匹配
var reg = /java([a-zA-Z]+)/g;
// 使用該正則的exec()方法匹配字符串str
var execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);
// 使用該正則的ecev()方法匹配字符串str2
execResult = reg.exec(str2);
console.log(execResult, reg.lastIndex);
從打印結(jié)果可以看出,對(duì)于str字符串的正則匹配時(shí),正常返回了結(jié)果,其lastIndex的值為16,還并沒有最終匹配結(jié)束,lastIndex值也沒有重置為0。這時(shí)候直接使用該正則表達(dá)式對(duì)str2進(jìn)行exec()方法調(diào)用,卻返回了null。為什么呢,正常應(yīng)該也可以匹配到str2字符的javascript字符啊。這是因?yàn)椋瑢?duì)str調(diào)用后,其lastIndex值被賦值為了16,那么下次對(duì)str2調(diào)用的時(shí)候,便從下標(biāo)16開始調(diào)用,str2中從下標(biāo)16開始匹配自然而然是沒有匹配到任何字符串。注意,正則表達(dá)式的實(shí)例屬性lastIndex是可讀可寫的屬性,所以為了避免這種情況,在對(duì)str2正則匹配前,先將其lastIndex屬性重置為0:
reg.lastIndex = 0;
execResult = reg.exec(str2);
console.log(execResult, reg.lastIndex);
所謂元字符,其實(shí)就是在正則表達(dá)式的不同上下文中有著特殊意義的標(biāo)點(diǎn)符號(hào),請(qǐng)看下面:
. * + ( ) $ / ");
嗯~沒錯(cuò),就是這幾個(gè)字符,通過不同的組合可以幫我們構(gòu)建出非常強(qiáng)大的正則表達(dá)式。注意,這些字符帶有特殊意義,如果就只是單純的項(xiàng)匹配這些字符,需要加/進(jìn)行轉(zhuǎn)義,例如.就只是匹配一個(gè)點(diǎn),沒有其他特殊意義。下面我們一一進(jìn)行介紹。
. : 匹配除了換行符和回車之外的任何字符,eg: /./ 匹配一個(gè)除換行回車之外的任意字符;
[] :? 匹配方括號(hào)里面的任意字符。方括號(hào)內(nèi)可以是1個(gè)字符也可以是多個(gè)字符。eg: [ab] 匹配字符a,也可以匹配字符b;[a- z] 可以匹配字母a到z任意一個(gè),-表示到的意思;[0-9]可以匹配數(shù)字0到9;也可以混合使用[a-zA-Z0-9]可以匹配小寫字母a到z,大寫字母A-Z,可以匹配數(shù)字0-9;
[^] : 匹配除了方括號(hào)內(nèi)^后面的任意字符,可以理解為[]的取反操作。eg: /[^ab]/ 匹配除了a和b以外的任意字符。?
| : 或,即匹配 | 左邊或者右邊的表達(dá)式。eg: /a|b/ 匹配字符a或者字符b
*? : 匹配0個(gè)或多個(gè)前面的表達(dá)式, eg: /a*/ 匹配0或者多個(gè)a,a、aa、aaa、aaaa等都是滿足匹配規(guī)則的。
+ : 匹配1個(gè)或多個(gè)前面的表達(dá)式,和*類似,但是至少要滿足匹配一次。eg: /a+/ 可以匹配1個(gè)或多個(gè)a,隱藏a、aa、aaa等都是合法的,但是bcdf是不符合匹配規(guī)則的,因?yàn)闆]有至少匹配到一個(gè)a。
");:? 匹配0和或1個(gè)前面的表達(dá)式,可以理解為前一項(xiàng)是可選的。和*與+類似,但是要注意三者的區(qū)別。
{n, m} : 匹配前一項(xiàng)n到m次,包含n次和m次。eg: /[0-9]{6,8}/ 可以匹配6到8位數(shù)字。
{n, } :? 匹配前一項(xiàng)至少n次。 eg: /[0-9]{11, }/ 至少匹配11位數(shù)字
{n} : 匹配前一項(xiàng)n次。 eg: /[0-9]{5}/? 匹配5位數(shù)字
需要注意的是:*和");可以匹配前一項(xiàng)0次,因此像類似 /a*/.test("bcdf") 是返回true的,因?yàn)樗ヅ涞搅?個(gè)a;而/a*/.exec("bcdf")也是返回了一個(gè)第一項(xiàng)是一個(gè)空字符串的數(shù)組,而不是返回null,也是因?yàn)槠ヅ淞?個(gè)a。
另一個(gè)需要注意的是,正則匹配默認(rèn)都是貪婪匹配。什么意思呢?就是盡可能多的匹配,比如用/a+/來匹配字符串a(chǎn)aabbbb時(shí),會(huì)匹配到aaa,即盡可能多匹配。類似的重復(fù)匹配時(shí)都是貪婪匹配的。然而可以使用這些元字符加上");/a+");再對(duì)aaabbbb匹配時(shí),則只會(huì)匹配到一個(gè)a,其他的*");? {}"); ");同理。
: 和一些字符組合使用會(huì)有特殊的意義:
w | 元符號(hào),等價(jià)于[a-zA-Z0-9_],匹配任何字母、數(shù)字、下劃線字符,這樣的字符也稱為單詞字符 |
W | 元符號(hào),等價(jià)于[^a-zA-Z0-9_],匹配除了字母、數(shù)字、下劃線字符之外的任何字符 |
d | 元符號(hào),等價(jià)于[0-9],匹配任何單個(gè)的數(shù)字字符 |
D | 元符號(hào),等價(jià)于[^0-9],匹配除了數(shù)字之外的任何單個(gè)字符 |
s | 元符號(hào),匹配空白字符,即空格、Tab字符和回車換行符 |
S | 元字符,匹配任何非空白字符 |
^ :匹配字符串的開始位置,或多行匹配模式中(即加了修飾符m)每一行的開始位置
$ : 匹配字符串的結(jié)束位置,或多行匹配模式下(即加了修飾符m)每一行的結(jié)束位置
^和$這兩個(gè)元字符,在日常開發(fā)中幾乎是最常見的了,幾乎大部分的正則表達(dá)式都是這種形式的:/^表達(dá)式$/。都知道是它的意思是匹配字符串的開始和結(jié)束為止,猛一看好像理解了,但是細(xì)細(xì)揣摩貌似又不知道到底是什么意思。下面我就細(xì)細(xì)說來:
這兩個(gè)字符和上面其他元字符不同的是,這個(gè)字符匹配的是位置,而不是具體匹配的某個(gè)字符。這么說,應(yīng)該清晰一點(diǎn)了,所以/^表達(dá)式$/就是從字符串開頭的位置開始,一直到結(jié)束的位置,都必須滿足匹配規(guī)則才行。再次強(qiáng)調(diào)下,^和$匹配的都只是一個(gè)位置,位置,位置。
: 匹配單詞邊界。這個(gè)也是用來匹配位置的,通俗的講,就是匹配區(qū)分單詞分割位置的。例如,兩個(gè)單詞之間的位置,第一個(gè)單詞前面的位置,最后一個(gè)單詞后面的位置,都是匹配的單詞位置。eg: /java/可以匹配單詞java,即匹配java字符兩邊都是單詞邊界的結(jié)果,對(duì)于字符串I love java very much則匹配成功,而字符串I love javascript very much則匹配不成功。因?yàn)榈谝痪涞膉ava兩邊空格都是單詞邊界,而javascipt雖然包含了java單詞,但是只滿足左邊是單詞邊界,其子串java的右邊是script子串,而不是單詞邊界,所以不滿足兩邊都是單詞邊界的匹配規(guī)則。
console.log(/java/.test("java")) // true
console.log(/java/.test("javascript")) // false
B:匹配非單詞邊界,是的反義詞。eg:/Bscript/ 對(duì)于字符串javascript是可以匹配成功的,因?yàn)槠渥哟畇cript的左側(cè)是java字符串,不是單詞邊界。而對(duì)于字符串script則是不成功的,因?yàn)槠渥髠?cè)什么都沒有,即左側(cè)就是一個(gè)單詞邊界。
console.log(/Bscript/.test("javascript")) // true
console.log(/Bscript/.test("script")) // false
js里面的斷言只支持先行斷言,又分為正向先行斷言和負(fù)向先行斷言。這么說比較繞口,讓人云里霧里的感覺,所以還是直接上例子:
");: 正向先行斷言,其實(shí)就是說");/java(");只能匹配javascript,不能匹配javaspring,java123等等。
");: 負(fù)向先行斷言,即");/java(");?只能匹配javaspring,java123等等,但不能匹配javascript。
() : 子表達(dá)式,也可以叫分組,就是把括號(hào)里面的表達(dá)式作為一個(gè)整體來處理。一個(gè)正則表達(dá)式里面可以有多個(gè)子表達(dá)式,子表達(dá)式里面也可以嵌套子表達(dá)式。在我們介紹exec()方法的時(shí)候說過,exec()返回一個(gè)增強(qiáng)的數(shù)組,數(shù)組第一項(xiàng)為該正則表達(dá)式的匹配結(jié)果,第二項(xiàng)及以后為對(duì)應(yīng)的子表達(dá)式的匹配結(jié)果。
// 沒有子表達(dá)式的正則exec()方法
var reg1 = /[a-z][0-9]/;
var str1 = "hello123";
console.log(reg1.exec(str1))
// 添加了子表達(dá)式的正則exec()方法
var reg2 = /([a-z])([0-9])/;
var str2 = "hello123";
console.log(reg2.exec(str2))
// 子表達(dá)式嵌套的情況
var reg3 = /(([a-z])([0-9]))/;
var str3 = "hello123";
console.log(reg3.exec(str3))
打印結(jié)果可以看出,加子表達(dá)式之后,比沒加之前多返回了幾項(xiàng),這幾項(xiàng)分別對(duì)應(yīng)每個(gè)子表達(dá)式匹配的結(jié)果。注意,當(dāng)有嵌套的情況下,子表達(dá)式的順序,其實(shí)就是所有的左括號(hào)從左到右出現(xiàn)的順序。
每一子表達(dá)式匹配到的值都會(huì)被保存下來,分別存在1,2,3……里面,也會(huì)保存在$1,$2,$3……兩者的區(qū)別是,1這種類型的是使用在正則表達(dá)式中的,$1這種類型的是使用在字符串的方法中。關(guān)于字符串方面會(huì)在文章后面的內(nèi)容講解。先看個(gè)例子吧:
// 需要匹配第一第二位都是數(shù)字,第三位和第一位必須相同,第四位和第二位必須相同的正則表達(dá)式
var reg4 = /(d)(d)12/;
// 打印為true,因第一位和第二位都是數(shù)字,第三位和第一的值相同,第四位和第二位的值也相同
console.log(reg4.test("1212")) // true
// 打印結(jié)果為false,因?yàn)榈谌坏闹岛偷谝晃坏牟灰粯?console.log(reg4.test("1232"))
從這正則表達(dá)式可以看到,要求匹配的第一位和第二位都是數(shù)字,那么后面的1和2是什么意思呢,就是說1就是第一個(gè)(d)匹配到的結(jié)果,2就是第二個(gè)(d)匹配到的結(jié)果。注意,這里的意思并不是說第三位第四位是和第一第二位匹配的規(guī)則相同的,而是說,加入第一位匹配到了數(shù)字2,那么第三位也只能數(shù)字2,如果第二位匹配到了數(shù)字4,那么第四位也必須是4才可以。那么最終的匹配結(jié)果就是類似1212, 4747等。eg: 左引號(hào)和右引號(hào)必須相匹配的情況,可以這樣子:/[""][^""]*1/,即首先是單引號(hào)或者雙引號(hào),后面是0到多個(gè)非單引號(hào)雙引號(hào)字符,最后如果第一個(gè)匹配了單引號(hào)則最后一個(gè)必須是單引號(hào),如果第一個(gè)匹配到了雙引號(hào)則最后也必須是雙引號(hào)。
注意在子表達(dá)式嵌套的情況下,1,2……對(duì)應(yīng)的其實(shí)就是左括號(hào)的值,不管它怎么嵌套。這么說應(yīng)該更好理解了。
那么問題來了,如果不想保存子表達(dá)式的值呢,或者說多個(gè)子表達(dá)式中我不想保存某些子表達(dá)式的值怎么辦呢?
("); : 一個(gè)問號(hào)加一個(gè)冒號(hào),成為無記憶匹配。他依然是對(duì)括號(hào)中里面的內(nèi)容進(jìn)行分組,但是不會(huì)捕獲子模式,即不會(huì)保存匹配到的值到1,2,3……中。現(xiàn)在我修改一下上面的例子再看:
// 需要匹配第一第二位都是數(shù)字,第三位和第二位必須相同
var reg4 = /(");false,因第一位和第二位都是數(shù)字,第三位和第二位的值不一樣
console.log(reg4.test("1212"))
// 打印結(jié)果為true,因?yàn)榈谌坏闹岛偷诙坏闹迪嗤?console.log(reg4.test("1232"))
從表達(dá)式可以看出,我們的第一個(gè)(");子表達(dá)式添加了無記憶匹配模式,所以后面的1里面存放的值就變成了后面的(d)匹配的結(jié)果。因此,子表達(dá)式設(shè)置了無記憶匹配模式后,1,2……便不會(huì)再存儲(chǔ)其匹配結(jié)果了,而是存儲(chǔ)后面沒有設(shè)置無記憶匹配模式的子表達(dá)式。
字符串方法小伙伴們都很熟悉,這里只說和正則匹配相關(guān)的方法。正則表達(dá)式本身就是用來處理字符串的匹配規(guī)則,那么相應(yīng)的字符串方法,當(dāng)然得和正則勾搭點(diǎn)關(guān)系啦~~好了,拉回正題,下面先列舉和正則有關(guān)的字符串方法:
match(regex) | 返回所有與正則表達(dá)式regex相匹配的子串?dāng)?shù)組 |
replace(regex,replacement) | 字符串替換。將字符串中的regex指定的子串替換為子串replacement |
search(regex) | 字符串搜索。查找正則表達(dá)式regex指定的模式在字符串中的開始位置 |
split(regex) | 字符串分割。使用正則表達(dá)式regex分割字符串,并將分割的結(jié)果以數(shù)組的形式返回 |
? (1) match方法:返回一個(gè)由匹配結(jié)果組成的數(shù)組,如果沒有匹配到任何結(jié)果則返回null。該方法接收一個(gè)正則表達(dá)式作為參數(shù),如果不是正則表達(dá)式,它會(huì)首先調(diào)用new RegExp()將參數(shù)轉(zhuǎn)換成正則表達(dá)式。
注意:如果正則參數(shù)不帶修飾符g,match方法不會(huì)進(jìn)行全局匹配,其效果和不加修飾符g的exec()方法返回的結(jié)果是一樣的。如果忘記了exec()方法,可以往回翻翻回顧一下。
"aaaa".match("b") // 返回null,因?yàn)闆]有匹配到任何內(nèi)容
下面看下正則表達(dá)式不帶修飾符g的例子:
console.log("abcd");.match(/a/))
在不是全局匹配的情況下,其返回結(jié)果和exec()方法如出一轍,如果表達(dá)式含有子表達(dá)式的話,數(shù)組的第二項(xiàng)及后續(xù)項(xiàng)是子表達(dá)式的匹配結(jié)果。如果是全局匹配的話,則會(huì)返回一個(gè)由所有匹配結(jié)果組成的數(shù)組:
// 不含有子表達(dá)式的全局匹配
console.log("1a2b3c4d5");.match(/[0-9]/g))
// 含有子表達(dá)式的全局匹配
console.log("1a2b3c4d5");.match(/[0-9]|(a)/g))
結(jié)果非常的直觀,在全局匹配模式下會(huì)返回所有匹配結(jié)果組成的數(shù)組。但是如果正則表達(dá)式含有子表達(dá)式的話,也會(huì)把子表達(dá)式的匹配結(jié)果返回出來。
? (2) replace()方法:用于字符串的替換,并返回替換后的結(jié)果。接收兩個(gè)參數(shù),第一個(gè)參數(shù)是匹配的規(guī)則,第二參數(shù)是用來替換的字符串。第一個(gè)參數(shù),可以是字符串,也可以是正則表達(dá)式。
字符串就不多說了,這里只說是正則表達(dá)式的情況,replace會(huì)根據(jù)正則表達(dá)式去匹配對(duì)應(yīng)的結(jié)果,然后將其替換成第二參數(shù):
// 正則表達(dá)式不帶修飾符g
console.log("abc1234".replace(/[a-z]/, "0"))
// 正則表達(dá)式帶修飾符g
console.log("abc1234".replace(/[a-z]/g, "0"))
輸出結(jié)果可以看出,在不加修飾符g的情況下,字符串的repalce方法不會(huì)全局檢索替換,而只是替換了第一次。在全局匹配模式下,replace方法會(huì)把所有的匹配結(jié)果全局替換成第二個(gè)參數(shù)對(duì)應(yīng)的字符串。
前文說子表達(dá)式的時(shí)候說到,正則表達(dá)式會(huì)把匹配結(jié)果存放在類似1,2和$1,$2的里面,在這里便可以用到$1,$2了。用法就是,在repealce()方法的第二個(gè)參數(shù)字符串中,$1,$2……不再是普通的字符串,而是有著特殊一樣的標(biāo)識(shí)符,對(duì)應(yīng)的值就是正則表達(dá)式每一個(gè)子表達(dá)式匹配到的結(jié)果:
// 定義一個(gè)匹配一個(gè)abc字符后面跟著一個(gè)數(shù)字的正則表達(dá)式
// 并將匹配結(jié)果替換成該子表達(dá)式的結(jié)果
console.log("abc1234".replace(/abc(d)/g, "$1")) // 1234
該替換方法,最終將abc1替換成了第一個(gè)子表達(dá)式匹配的結(jié)果1,所以最終結(jié)果是1234。
repalce()方法的第二次參數(shù),不僅可以是字符串,還可以是一個(gè)函數(shù),如果是函數(shù)則對(duì)每一次的匹配結(jié)果調(diào)用該函數(shù)。該函數(shù)必須返回一個(gè)字符串,如果沒有reutrn語句,則是跟正常函數(shù)一樣默認(rèn)返回undefined。如果返回的不是字符串類型,會(huì)將其轉(zhuǎn)換成字符串類型:
console.log("abc1234".replace(/abc(d)/g, function(){
return "hello"
}))
// 打印結(jié)果為hello234
從結(jié)果可以看出,將匹配到的字符串a(chǎn)bc1替換成了hello字符串。
同時(shí),該函數(shù)有多個(gè)參數(shù),第一個(gè)參數(shù)是當(dāng)前匹配到的結(jié)果,第二個(gè)參數(shù)開始往后是子表達(dá)式匹配到的結(jié)果,可以有0-n個(gè)。再后面一個(gè)參數(shù)當(dāng)前匹配結(jié)果在原字符串中的下標(biāo),最后一個(gè)參數(shù)原字符串:
"abc1234".replace(/abc(d)(d)/g, function(a,b,c,d,f){
console.log(a,b,c,d,f)
})
// 打印結(jié)果為 abc12 1 2 0 abc1234
可以看到打印的結(jié)果abc12是正則匹配到的結(jié)果,1是第一個(gè)子表達(dá)式(d)匹配的結(jié)果,2是第二個(gè)子表達(dá)式(d)匹配到的結(jié)果,0是匹配結(jié)果字符串在原字符串中的下標(biāo),abc1234是原字符串。再看下匹配到多次結(jié)果的情況:
"abc1234abc567".replace(/abc(d)(d)/g, function(a,b,c,d,f){
console.log(a,b,c,d,f)
})
// 下面是打印結(jié)果
abc12 1 2 0 abc1234abc567
abc56 5 6 7 abc1234abc567
對(duì)于有多次匹配結(jié)果的情況,會(huì)多次調(diào)用該函數(shù)。
? (3) search()方法查找匹配結(jié)果在原字符串中的位置。接收一個(gè)字符串或者正則表達(dá)式作為查詢參數(shù)。最終返回查詢到的下標(biāo),沒有查詢到則返回-1。
// 參數(shù)為字符串時(shí)
console.log("abcd".search("d")) // 3
// 參數(shù)為正則表達(dá)式
console.log("abcd".search(/d/)) // 3
上面演示了簡(jiǎn)單的查找,對(duì)于簡(jiǎn)單的查找,完全是可以使用字符串的indexOf()方法,查找結(jié)果都是一樣的。
console.log("abcd".indexOf("d")) // 3
需要注意的地方就是:1.該方法不會(huì)進(jìn)行全局查找,即會(huì)忽略修飾符g,一旦匹配到結(jié)果即返回下標(biāo); 2.會(huì)忽略正則表達(dá)式的lastIndex屬性,即每次查找都從字符串開始位置重新開始。
var str = "abcddadd"
// 只返回了第一個(gè)d字符的洗標(biāo),忽略修飾符g
console.log(str.search(/d/g)) // 依舊輸出了3
// 第二次調(diào)用,依舊輸出3,即忽略了lastIndex屬性
console.log(str.search(/d/g))
? (4) split()方法: 用于字符串分割,接收一個(gè)用于分割字符串的字符串或者正則表達(dá)式作為參數(shù),第二個(gè)參數(shù)為可選的指定返回分割后的數(shù)組長(zhǎng)度。
// 第一個(gè)參數(shù)為""時(shí), 將按字符分割字符串
// 這在我們需要把字符串作為組數(shù)處理時(shí)非常有用
"asdfg".split("") // ["a", "s", "d", "f", "g"]
// 可以接收第二參數(shù),作為返回后的數(shù)組長(zhǎng)度
"asdfg".split("", 3) // ["a", "s", "d"]
// 以字符串s進(jìn)行跟個(gè)
"asdfg".split("s") // ["a", "dfg"]
// 以正則表達(dá)式匹配結(jié)果進(jìn)行分割
"asdfg".split(/s/) // ["a", "dfg"]
比如下面,一個(gè)簡(jiǎn)易版的解析url中鍵值對(duì)參數(shù)
/*
* 簡(jiǎn)易解析url中鍵值對(duì)參數(shù)
* @param url { String } 待解析的url
* @return { key1: 1, key2: 2} 返回解析后的鍵值對(duì)的對(duì)象
*/
const parseQueryString = url => {
if (!url) throw Error("缺少待解析url")
let result = {}
const query = url.split("");)[1]
query && query.split("&").forEach(e => {
const parts = e.split("=");
result[parts[0]] = parts[1];
})
return result;
}
parseQueryString("www.baidu.com");) // {ke1: 1, key2: 2}
那就再扯一下數(shù)組的join()方法吧,可以理解為字符串split()方法的反作用方法。該方法用于將數(shù)組轉(zhuǎn)換成字符串,接收一個(gè)參數(shù),作為拼接符,默認(rèn)是英文逗號(hào):
[1,2,3,4,5].join() // "1,2,3,4,5" // 默認(rèn)逗號(hào)拼接
[1,2,3,4,5].join("a") // "1a2a3a4a5" // 自定義用字符a拼接
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/7013.html
摘要:然而,操作作為前端的基礎(chǔ),自誕生以來便左右著我們的頁面效果。不管任何時(shí)候,依舊是前端必須掌握且需要投入一定時(shí)間研究的基礎(chǔ)。不能只停留在事件的操作或者只是掌握那幾個(gè)最常見的。在當(dāng)前MVVM大行其道的環(huán)境下提到DOM一詞,很多人可能會(huì)感到有些詫異。這種差詫異或許來自于類似都什么年底了還操作DOM啊的聲音!說的沒錯(cuò),MVVM時(shí)代,虛擬dom東征西戰(zhàn),一枝獨(dú)秀,著實(shí)不可否認(rèn)其強(qiáng)大的威力。 然而,DO...
摘要:值得一提的是每篇文章都是我用心整理的,編者一貫堅(jiān)持使用通俗形象的語言給我的讀者朋友們講解機(jī)器學(xué)習(xí)深度學(xué)習(xí)的各個(gè)知識(shí)點(diǎn)。今天,紅色石頭特此將以前所有的原創(chuàng)文章整理出來,組成一個(gè)比較合理完整的機(jī)器學(xué)習(xí)深度學(xué)習(xí)的學(xué)習(xí)路線圖,希望能夠幫助到大家。 一年多來,公眾號(hào)【AI有道】已經(jīng)發(fā)布了 140+ 的原創(chuàng)文章了。內(nèi)容涉及林軒田機(jī)器學(xué)習(xí)課程筆記、吳恩達(dá) deeplearning.ai 課程筆記、機(jī)...
摘要:更多資源請(qǐng)文章轉(zhuǎn)自月份前端資源分享的作用數(shù)組元素隨機(jī)化排序算法實(shí)現(xiàn)學(xué)習(xí)筆記數(shù)組隨機(jī)排序個(gè)變態(tài)題解析上個(gè)變態(tài)題解析下中的數(shù)字前端開發(fā)筆記本過目不忘正則表達(dá)式聊一聊前端存儲(chǔ)那些事兒一鍵分享到各種寫給剛?cè)腴T的前端工程師的前后端交互指南物聯(lián)網(wǎng)世界的 更多資源請(qǐng)Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://github.com/jsfr...
摘要:是什么是一個(gè)用寫的插件,可以在成千上萬數(shù)十萬個(gè)文件中,通過模糊查找的方式,快速找到目標(biāo)文件。它還有很多衍生功能快速打開或定位某個(gè)最近使用的文件包括函數(shù)類變量等命令歷史文件中的某一行的等等。友情鏈接,也許是最好的模糊查詢插件 提到vim的模糊查找插件,很多人第一反應(yīng)是ctrlp.vim,ctrlp知名度很高,但跟其它的同類插件相比,它的唯一優(yōu)點(diǎn)是用vimL編寫(這讓它的性能是所有同類插件...
閱讀 3403·2021-09-22 15:01
閱讀 532·2019-08-30 11:11
閱讀 963·2019-08-29 16:17
閱讀 1216·2019-08-29 12:23
閱讀 2033·2019-08-26 11:48
閱讀 3185·2019-08-26 11:48
閱讀 1426·2019-08-26 10:33
閱讀 1935·2019-08-26 10:30