摘要:正則表達式基礎知識正則表達式是計算機科學的一個概念。正則表達式使用單個字符竄來描述匹配一系列符合某個句法規則的字符竄。正則表達式的文本字符竄。第二個參數是正則表達式分組內容,沒有分組則沒有該參數。
正則表達式-基礎知識Review
正則表達式(Regular Expression)是計算機科學的一個概念。 正則表達式使用單個字符竄來描述、匹配一系列符合某個句法規則的字符竄。 在很多文本編輯器里, 正則表達式通常用來被檢索替換哪些符合某個模式的文本。
創建JavaScript通過內置對象 RegExp支持正則表達式, 有兩種方式創建正則表達式對象, 如果我們想匹配字符竄中<%xxx%>兩個百分號分割的字符竄可以這么寫。
構造函數
</>復制代碼
var regExp = new RegExp("<%[^%>]+%", "g");
字面量
</>復制代碼
var regExp = /<%[^%>]%>/g;
最后的g代表全局, 還有幾個修飾符
RegExp實例對象有五個屬性
g: global, 全文搜索,不添加的話搜索到第一個結果停止搜索。
i: ignore case, 忽略大小寫,默認大小寫敏感。
m: multiple lines, 多行搜索。
lastIndex: 是當前表達式模式首次匹配內容中最后一個字符的下一個位置,每次正則表達式匹配成功匹配時, lastIndex屬性值都會隨之改變。
sourse:正則表達式的文本字符竄。
除了正則表達式編譯為內部格式從而使執行更快的compile()方法, 對象還有兩個我們常用的方法。
元字符正則表達式讓人望而卻步的一個重要原因就是轉譯字符太多, 組合非常多, 但是正則表達式的元字符(在正則表達式中具有特殊意義的專用字符,可以用來規定其前導字符)并不多
</>復制代碼
() [] {} ^ $ | ? * + .
并不是每個元字符都有特定的意義,在不同的組合中元字符有不同的意義, 分類看一下
t 水平制表符 tab
r 回車符 carriage return
n 換行符 newline
f page feed 換頁符
cX 與X對應的控制字符(Ctrl + X )
v 垂直制表符
0 空字符
字符類一般情況下正則表達式一個字符(轉譯字符算一個) 對應字符竄一個字符,表達式 abt 的含義
</>復制代碼
ab水平制表符
但是我們可以使用元字符[]來構建一個簡單的類, 所謂類是指,符合某些特征的對象, 是一個泛指,而不是特指某個字符了, 我們可以使用表達式[abc], 把字符a或b或c歸為一類,表達式可以匹配這類的字符。
元字符[]組合可以創建一個類,我們還可以使用元字符^創建反向類/負向類,反向類的意思是不屬于XXX類的內容, 表達式1表示不是字符a或b或c的內容。
范圍類按照上面的說明如果希望匹配單個數字那么表達式是這樣的
</>復制代碼
[0123456789]
如果是字母那么。。。 好麻煩, 正則表達式還提供了范圍類,我們可以使用x-y來連接兩個字符表示從x到y的任意字符, 這是個閉區間, 也就是說包含x和y本身, 這樣匹配小寫字母就很簡單了。
預定義類</>復制代碼
[a-z]
剛才使用正則我們創建了幾個類,來表示數字,字母等,但這樣寫很麻煩,正則表達式為我們了幾個常用的預定義類來匹配常見的字符。
字符 | 等價類 | 含義 |
---|---|---|
. | [^rt] | 除了回車符和換行符之外的所有字符 |
d | [0-9] | 數字字符 |
D | [^0-9] | 數字字符 |
s | [ x0Bf ] | 空白符 |
S | [^t x0Bf ] | 非空白符 |
w | [a-zA-Z_0-9] | 字母,數字,下劃線 |
W | [^a-zA-Z_0-9] | 非字母,數字,下劃線 |
有了這些預定義類, 寫一些正則就很方便了, 比如我們希望匹配一個 ab + 數字 + 任意字符的字符竄, 就可以寫了abd.
可以把正則表達式,想象成一種模式,字符竄匹配正則表達式定義的模式的結果
</>復制代碼
string.match(regExpPattern)
邊界
正則表達式還提供了幾個常用的邊界匹配字符。
字符 | 含義 |
---|---|
^ | 以xxx開頭, ^ 開頭的匹配參照對象是整個字符竄 |
$ | 以xxx結尾, $ 結尾的匹配參照對象也是整個字符竄 |
b | 單詞邊界, "-"也是單詞邊界! |
B | 非單詞邊界 |
</>復制代碼
^ 開頭的匹配參照對象是整個字符竄,
$ 結尾的匹配參照對象也是整個字符竄,
限制的是整個字符竄。
var regExpPattern = /^hdm/g;
"h2m h4m h2m".match(regExpPattern); // h2m, 記住這是以整個字符竄去匹配的
//同理
var regExpExpPattern = /hdm$/g;
"h2m h4m h4m".match(regExpPattern); // h4m
//使用場景 手機號匹配
"13423454234".match(/^1d{10}$/g)
量詞
之前,介紹的方法都是一一匹配,如果希望匹配一個連續20次數字的字符竄難道我們需要寫成這樣?
</>復制代碼
ffffdffffdffffdffffdffffdffffdffffddd..
為此正則表達式引入了一些量詞
字符 | 含義 |
---|---|
? | 出現零次或一次(最多出現一次) |
+ | 出現一次或多次(至少出現一次) |
* | 出現零次或多次(任意次) |
{n} | 出現n次 |
{n,m} | 出現n到m次 |
{n,} | 至少出現n次 |
{,m} | 最多出現m次 |
</>復制代碼
var regExp = /w+Bryon/
regExp.test("hi Bryon"); // true
regExp.test("Welcome Byron"); // true
regExp.test("Byron"); //false
//匹配帶有3到1個小數的數字
var reg = /d+.d{1,3}
貪婪模式與非貪婪模式
看了量詞的介紹,也許愛思考的同學會想到關于匹配原則的一些問題, 比如{3,5} 這個量詞, 要是在句子中出現了十次, 那么他是每次匹配三個還是五個,反正3,4,5都滿足3~5的條件。
量詞在默認下是盡可能多的匹配的,也就是大家常說的貪婪模式。
</>復制代碼
// ["12345","6789"];
"12345679".match(/d{3,5}/g);
既然有貪婪模式,那么肯定會有非貪婪模式,讓正則表達式盡可能少的匹配,u額就是說一旦成功匹配不再繼續嘗試,做法很簡單, 在量詞后加上?即可
</>復制代碼
//["123","456","789"]
"123456789".match(/d{3,5}?/g);
分組
有時候希望使用量詞的時候匹配多個字符,而不是像上面例子只是匹配一個,比如希望匹配Byron出現20次的字符竄,寫成Byron{20}的話匹配的是Byro+n出現20次。
</>復制代碼
//寫成Byron{20}的話匹配的是Byro+n出現20次。
/Byron{20}/g
怎么把Byron作為一個整體呢? 使用()就可以達到此目的,在正則中成為分組。
</>復制代碼
//分組在regExp.exec(stringObj)中會多帶帶顯示在返回結果中。
(Byron){20}
或 |
如果希望匹配Byron或Casper出現20次該怎么辦呢? 可以使用字符| 達到或的功效
</>復制代碼
(Byron|Casper){20}
使用分組的正則表達式會把匹配項也放到分組中,默認是按數字編號分發的,可以根據編號獲得捕獲的分組內容,這在一些希望具體操作第幾個匹配項的函數中很有用。
</>復制代碼
// Group 1 : Byron , Group 2: ok
(Byron).(ok)
分組嵌套
如果有分組嵌套的情況,外面的組的編號靠前
</>復制代碼
// group 1: (^|%>)[^
]*, Group 2: (^|%>)
((^|%>)[^
]*)
忽略分組
有時候我們不希望捕獲某些分組,只需要在分組內加上?: 就可以了, 這并不意味著該分組內容不屬于正則表達式,只是不會給這個分組加編號而已。
</>復制代碼
(?:Bryon).(ok)
前瞻
表達式 | 含義 |
---|---|
exp1(?=exp2) | 匹配后面是exp2的exp1 |
exp1(?!exp2) | 匹配后面不是exp2的exp1 |
</>復制代碼
var regExp = /good(?=Byron)/;
regExp.exec("goodByron123"); // ["good"]
regExp.exec("goodCapser123"); // null
通過上面例子可以看出exp1(?=exp2)表達式, 但只有其后面內容是exp2的時候才會匹配,也就是兩個條件,exp1(?!exp2)比較類似。
正則表達式相關的方法RegExp.prototype.test(str)
該方法用于測試字符竄參數中是否匹配正則表達式模式,如果存在則返回true,否則返回false。
</>復制代碼
var reg = /d+.d{1,2}$/g;
reg.test("123.45"); // true
reg.test("0.2"); // true
reg.test("a.34"); //false
reg.test("34.5678"); //false
</>復制代碼
//判斷手機號是否正確
function isPhoneNum(phoneNum) {
var phoneNumberTester = /^1d{10}$/;
return phoneNumberTester.test(phoneNum);
}
RegExp.prototype.exec(str)
該方法用于正則表達式模式在字符竄中運行查找,如果exec()找到匹配的文本,則返回一個結果,否則返回null
除了數組元素和length屬性之外, exec()方法返回對象還包括兩個屬性。
index屬性聲明的是匹配文本的第一個字符的位置。
input屬性則存放的是被檢索的字符竄string。
非全局調用
調用非全局的RegExp對象的exec()時,返回數組的第一個元素是與正則表達式相匹配的文本,第二個元素是與RegExpObject的第一個子表達式相匹配的文本(如果有的話), 第三個元素時與RegExp對象的第二個子表達式相匹配的文本(如果有的話),以此類推。
全局調用
調用全局的RegExp對象的exec()時,它會在RegExp實例的lastIndex屬性指定的字符處開始檢索字符竄string
當exec()找到了與表達式相匹配的文本時, 在匹配后, 它將把RegExp實例的lastIndex屬性設置為匹配文本的最后一個字符的下一個位置??梢酝ㄟ^反復調用exec()方法來遍歷字符竄中的所有哦匹配文本。
當exec()再也找不到匹配的文本時,它將返回null,并把lastIndex屬重置為0。
</>復制代碼
var reg = /d/g;
var r = reg.exec("a1b2c3");
console.log(r);
console.log(reg.lastIndex); // 2
r = reg.exec("a1b2c3");
console.log(reg.lastIndex); // 4
</>復制代碼
var reg = /d/g;
while (r = reg.exec("a1b2c3")) {
console.log(r.index + ":" + r[0])
}
//1:1 , 3:2, 5:3
String.prototype.search(reg)
search()方法用于檢索字符竄中指定的子字符串,或檢索與正則表達式相匹配的子字符竄。
search()方法不執行全局匹配,它將忽略標志g, 它同時忽略正則表達式對象的lastIndex屬性,并且總是從字符竄的開始進行檢索,這意味著它總是返回字符竄的第一個匹配的位置。
String.prototype.match(reg)
match()方法將檢索字符竄,以找到一個或多個與regexp匹配的文本。但regexp是否具有標志g對結果影響很大。
非全局調用
如果regexp沒有標志g,那么match()方法就只能在字符竄中執行一次匹配。如果沒有找到任何匹配的文本,match()將返回null。否則它將返回一個數組,其中存放了與它找到的匹配文本有關的信息。
該數組的第一個元素存放的是匹配文本,而其余的元素存放的是與正則表達式的子表達式匹配的文本。除了這些常規的數組元素之外,返回的數組還含有兩個對象屬性。
index屬性聲明的是匹配文本的起始字符在字符竄中的位置。
input屬性聲明的是對stringObject的引用。
String.prototype.replace(reg, replaceStr|| function callback())
關于string對象的replace方法, 我們最常用的是傳入兩個字符竄的做法,但這種做法有個缺陷,只能replace一次。
</>復制代碼
"abcabcabc".replacce("bc", "X") //aXabcabc
replace方法的第一個參數還可以傳入RegExp對象,傳入正則表達式可以使replace方法更加強大靈活
</>復制代碼
"abcabcabc".replace(/bc/g, "X"); //aXaXaX
"abcabcabc".replace(bc/gi, "X"); // aXaXaX
如果replace方法的第一個參數傳入的是帶分組的正則表達式,我們在第二個參數中可以使用$1...$9來獲取相應分組內容, 比如希望把字符竄1<%2%>34>%567%>89的<%x%>換為$#x#$, 我們可以這樣
"1<%2%>34>%567%>89的<%x%>".replace(/<%(d+)%>)/g, "@#$1#@");
// 1@#2#@34@#567#@89
當然還有很多方式可以達到這一目的,這里只是演示一下利用分組內容,我們在第二個參數中使用@#$1#@, 其中$1表示被捕獲的分組內容弄, 在一些js模板函數中可以經常見到這種方式替換字符竄。
可以通過修改replace方法的第二個參數,使replace更加強大,在前面的介紹中,只能把所有匹配替換為固定內容,但如果我希望把一個字符竄中所有數字,都用小括號包起來該怎么弄?
</>復制代碼
"2398sdadads1smdsa3mmm23mmmbb".replace(/d+/g, function(matchedStr, groupContent$, index, strObj ) {
return "(" + matchedStr + ")";
})
把replace方法的第二個參數傳入一個function,這個function會在每次匹配替換的時候調用,算是個每次替換的回調函數,我們使用了回調函數的第一個參數,也就是匹配內容,其實回調函數一共有四個參數。
第一個參數很簡單,是匹配字符竄。
第二個參數是正則表達式分組內容,沒有分組則沒有該參數。
第三個參數是匹配項在字符竄中的index。
第四個參數則是原字符竄。
例子
</>復制代碼
"2398rsjdhahd2131kksdajdj23".replace(/d+/g, function(matchedSubStr,index, strObj) {
console.log(matchedSubStr + "
" + index + "
" + strObj);
return "(" + matchedSubStr +")";
})
//2398 0 2398rsjdhahd2131kksdajdj23
//2131 12 2398rsjdhahd2131kksdajdj23
//23 24 2398rsjdhahd2131kksdajdj23
這是沒有分組的情況,打印出來的分別是匹配內容、匹配項index和原字符竄,看個有分組的。
</>復制代碼
"<%1%><%2%><%3%>".replace(/<%([^%>]+)%>/g, function(matchedStr, group, index, thisStrObj) {
console.log(matchedStr + "
" + group + "
" + index + "
" + thisStrObj);
return group;
})
//<%1%> 1 0 <%1%><%2%><%3%>
//<%2%> 2 5 <%1%><%2%><%3%>
//<%3%> 3 10 <%1%><%2%><%3%>
//"123"
String.prototype.split(reg)
使用split方法把字符竄分割為字符數組
</>復制代碼
"a,b,c,d".split(",");
// ["a","b","c","d"]
和replace方法類似,在一些復雜的分割情況下我們可以使用正則表達式解決
</>復制代碼
"a1b2c3d".split(/d/); // ["a","b","c","d"]
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98171.html
摘要:翻譯行代碼創造模板引擎一想看博客原文鏈接,請點擊下方一個非常好用的學習正則表達的網站正則表達式圖文解說網站譯文事情的起因,我想編寫一個邏輯簡單的模板引擎,它可以很好滿足我現在的需求。,表示全局匹配。 翻譯_20行代碼創造JavaScript模板引擎(一) 想看博客原文鏈接,請點擊下方 JavaScript template engine in just 20 lines 一個非常好用...
摘要:寫在最后近年來,隨著人們思想觀念的改變,相親也逐漸得到年輕人的接受與認可,特別是對于那些圈子比較窄,接觸不到異性的人而言。 前不久,小編刷到這樣一條短視頻,1.7億...
摘要:能夠開發開源組件的開發者本身素質相對較高,代碼質量較高,也使開源組件出漏洞的可能性較小。這種對比明顯反應出開源組件和開源應用在安全漏洞關注度上的差距。另一個例子,我們通過修改邏輯運算符改變開發者正常的判斷流程,造成安全問題。 開源組件是我們大家平時開發的時候必不可少的工具,所謂『不要重復造輪子』的原因也是因為,大量封裝好的組件我們在開發中可以直接調用,減少了重復開發的工作量。開源組件和...
摘要:阿里妹導讀提到盒馬鮮生,除了新鮮的大龍蝦以外,大家印象最深的就是快速配送門店附近公里范圍內,分鐘送貨上門。系統異常業務異常的處理,上線時門店灰度方案一個門店出問題,不影響整個盒馬門店,緩存機制柔性可用重試機制事務處理串并行打日志等等。 showImg(https://segmentfault.com/img/remote/1460000018587196); 阿里妹導讀:提到盒馬鮮生...
閱讀 3056·2021-11-22 09:34
閱讀 3647·2021-08-31 09:45
閱讀 3861·2019-08-30 13:57
閱讀 1682·2019-08-29 15:11
閱讀 1687·2019-08-28 18:04
閱讀 3232·2019-08-28 17:59
閱讀 1570·2019-08-26 13:35
閱讀 2195·2019-08-26 10:12