摘要:也叫零寬度正回顧后發斷言,它斷言自身出現的位置的前面能匹配表達式。同時使用了兩種斷言匹配以空白符間隔的數字再次強調,不包括這些空白符。
緣起
正則表達式就是一把利器,拿出來的時候往往無往不利, 但是我們常常卻將之束之高閣, 只因她不是那么漂亮,不那么讓人印象深刻.
基礎知識常用元字符
標識 | 說明 |
---|---|
. | 匹配除換行符以外的任意字符 |
w | 匹配字母或數字或下劃線或漢字, 若僅限英文等價于[a-z0-9A-Z_] |
s | 匹配任意的空白符,包括空格,制表符(Tab),換行符,中文全角空格等 |
d | 匹配數字 |
匹配單詞的開始或結束 | |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結束 |
反義字符
標識 | 說明 |
---|---|
W | 匹配任意不是字母,數字,下劃線,漢字的字符 |
S | 匹配任意不是空白符的字符 |
D | 匹配任意非數字的字符 |
B | 匹配不是單詞開頭或結束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou這幾個字母以外的任意字符 |
重復
標識 | 說明 |
---|---|
* | 重復零次或更多次 |
+ | 重復一次或更多次 |
? | 重復零次或一次 |
{n} | 重復n次 |
{n,} | 重復n次或更多次 |
{n,m} | 重復n到m次 |
分支條件 |
為了解決類似下面的問題
(?0d{2}[) -]?d{8} 匹配類似(010)88886666,或022-22334455,或02912345678等電話號碼. 首先是一個轉義字符(,它能出現0次或1次(?),然后是一個0,后面跟著2個數字(d{2}),然后是)或-或空格中的一個,它出現1次或不出現(?),最后是8個數字(d{8})
分支條件就是將能夠涉及到的所有情況都通過|列舉出來, 相當于程序代碼的||, 如果前部分滿足條件, 則不會在判斷后部分.
0d{2}-d{8}|0d{3}-d{7}這個表達式能匹配兩種以連字號分隔的電話號碼:一種是三位區號,8位本地號(如010-12345678),一種是4位區號,7位本地號(0376-2233445)。
(0d{2})[- ]?d{8}|0d{2}[- ]?d{8} 匹配3位區號的電話號碼,其中區號可以用小括號括起來,也可以不用,區號與本地號間可以用連字號或空格間隔,也可以沒有間隔
分組
使用()將滿足條件的表達式隔離出來作為獨立的一部分
如:
(d{1,3}.){3}d{1,3}
((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?)
將2[0-4]d|25[0-5]|[01]?dd?當作一個整體即可
一些示例
aw*匹配以字母a開頭的單詞——先是某個單詞開始處(b),然后是字母a,然后是任意數量的字母或數字(w*),最后是單詞結束處()。
d+匹配1個或更多連續的數字。這里的+是和類似的元字符,不同的是匹配重復任意次(可能是0次),而+則匹配重復1次或更多次。
w{6} 匹配剛好6個字符的單詞
零寬斷言
查找在某些內容(但并不包括這些內容)之前或之后的東西,也就是說它們像,^,$那樣用于指定一個位置,這個位置應該滿足一定的條件(即斷言).
標識 | 說明 |
---|---|
(?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 |
(?!exp) | 匹配后面跟的不是exp的位置 |
(? | 匹配前面不是exp的位置 |
(?=exp)也叫零寬度正預測先行斷言,它斷言自身出現的位置的后面能匹配表達式exp。比如w+(?=ing),匹配以ing結尾的單詞的前面部分(除了ing以外的部分),如查找I"m singing while you"re dancing.時,它會匹配sing和danc。
(?<=exp)也叫零寬度正回顧后發斷言,它斷言自身出現的位置的前面能匹配表達式exp。比如(?<=re)w+會匹配以re開頭的單詞的后半部分(除了re以外的部分),例如在查找reading a book時,它匹配ading。
(?<=s)d+(?=s),同時使用了兩種斷言, 匹配以空白符間隔的數字(再次強調,不包括這些空白符)。
為了解決:
w*q[^u]w*匹配包含后面不是字母u的字母q的單詞。但是如果多做測試(或者你思維足夠敏銳,直接就觀察出來了),你會發現,如果q出現在單詞的結尾的話,像Iraq,Benq,這個表達式就會出錯。這是因為[^u]總要匹配一個字符,所以如果q是單詞的最后一個字符的話,后面的[^u]將會匹配q后面的單詞分隔符(可能是空格,或者是句號或其它的什么),后面的w*b將會匹配下一個單詞,于是w*q[^u]w*就能匹配整個Iraq fighting。負向零寬斷言能解決這樣的問題,因為它只匹配一個位置,并不消費任何字符。現在,我們可以這樣來解決這個問題:w*q(?!u)w*。
(?!exp)也叫零寬度負預測先行斷言, 斷言此位置的后面不能匹配表達式exp, d{3}(?!d)匹配三位數字,而且這三位數字的后面不能是數字;((?!abc)w)+匹配不包含連續字符串abc的單詞。
(?也叫零寬度負回顧后發斷言, 斷言此位置的前面不能匹配表達式exp:(?
一個更復雜的例子:(?<=<(w+)>).*(?=1>)匹配不包含屬性的簡單HTML標簽內里的內容。(?<=<(w+)>)指定了這樣的前綴:被尖括號括起來的單詞(比如可能是),然后是.*(任意的字符串),最后是一個后綴(?=1>)。注意后綴里的/,它用到了前面提過的字符轉義;1則是一個反向引用,引用的正是捕獲的第一組,前面的(w+)匹配的內容,這樣如果前綴實際上是的話,后綴就是了。整個表達式匹配的是和之間的內容(再次提醒,不包括前綴和后綴本身)。
貪婪與懶惰
貪婪: 盡可能匹配最長的字符串
懶惰: 匹配滿足條件的第一個字符串
懶惰限定符
標識 | 說明 |
---|---|
*? | 重復任意次,但盡可能少重復 |
+? | 重復1次或更多次,但盡可能少重復 |
?? | 重復0次或1次,但盡可能少重復 |
{n,m}? | 重復n到m次,但盡可能少重復 |
{n,}? | 重復n次以上,但盡可能少重復 |
a.*?b匹配最短的,以a開始,以b結束的字符串。如果把它應用于aabab的話,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)
為什么第一個匹配是aab(第一到第三個字符)而不是ab(第二到第三個字符)?簡單地說,因為正則表達式有另一條規則,比懶惰/貪婪規則的優先級更高:最先開始的匹配擁有最高的優先權——The match that begins earliest wins。關鍵字
match
語法: str.match(reg), 參數可傳入字符串或者正則表達式.
關鍵注意正則表達式是否攜帶g, 判斷實現全局匹配.
如果匹配成功, 返回匹配的值, 取返回數據的[0]元素; 如果失敗,返回null
var str = "aaabbbcccffffdeeefff"; strResult = str.match(/aaa(S*)fff/); console.log(strResult); /* 返回一個類數組, 可使用Array.prototype.slice.call(strResult)轉化為真正的數組 ["aaabbbcccffffdeeefff", "bbbcccffffdeee", index: 0, input: "aaabbbcccffffdeeefff", groups: undefined] ["原字符串", "截取出來的字符串", "位置編碼", "輸入", "組"] */
exec
語法:reg.exec(str)
檢索字符串中指定的值。匹配成功返回一個數組,匹配失敗返回null。
test
直接用來判斷是否正確, 比較簡單
compile
compile() 方法用于改變 RegExp。
compile() 既可以改變檢索模式,也可以添加或刪除第二個參數。
var reg=/hello/; console.log(reg.exec("hellojs"));//["hello"] reg.compile("Hello"); console.log(reg.exec("hellojs"));//null reg.compile("Hello","i"); console.log(reg.exec("hellojs"));//["hello"]match和exec對比
相似點:
match和exec在匹配成功時返回的都是數組,在沒有匹配上時返回的都是null
不同點
1.全局匹配
當不使用全局匹配的時候,match和exec基本一致
var s = "aaa bbb ccc"; var reg = /w+/;//沒有g var rs_match = s.match(reg); var rs_exec = reg.exec(s); console.log("match:",rs_match); console.log("exec:",rs_exec);
當使用全局匹配的時候,match和exec返回數據不同
match直接以數組的形式返回匹配的所有數據
exec返回的數據的格式和未使用全局匹配一致, 但是是逐個匹配目標字符串. 返回的index下標能夠獲取第幾個匹配的初始位置.
var s = "aaa bbb ccc"; var reg = /w+/g;//有g var rs_match1 = s.match(reg); var rs_match2 = s.match(reg); var rs_exec1 = reg.exec(s); var rs_exec2 = reg.exec(s); console.log("match1:",rs_match1); console.log("match2:",rs_match1); console.log("exec1:",rs_exec1); console.log("exec2:",rs_exec2);
2.分組
無全局匹配分組時,match和exec返回結果相同。
由于正則表達式采用了括號分組,所以在返回匹配結果的同時,依次返回該結果的所有分組, 如上面示例str.match(/aaa(S*)fff/)返回結果, 類數組的第二個元素就是分組(()中的數據)的元素.
var s = "aaa1 bbb2 ccc3"; var reg = /(w+)(d{1})/;//兩個分組,無g var rs_match1 = s.match(reg); var rs_match2 = s.match(reg); var rs_exec1 = reg.exec(s); var rs_exec2 = reg.exec(s); console.log("match1:",rs_match1); console.log("match2:",rs_match1); console.log("exec1:",rs_exec1); console.log("exec2:",rs_exec2);
全局匹配分組時,match和exec返回結果不同。
match會返回所有匹配到的結果;
exec會返回本次匹配到的結果,若表達式中出現分組,則會依次返回本次匹配的全部分組:
var s = "aaa1 bbb2 ccc3"; var reg = /(w+)(d{1})/g; var rs_match1 = s.match(reg); var rs_match2 = s.match(reg); var rs_exec1 = reg.exec(s); var rs_exec2 = reg.exec(s); var rs_exec3 = reg.exec(s); var rs_exec4 = reg.exec(s); console.log("match1:",rs_match1); console.log("match2:",rs_match1); console.log("exec1:",rs_exec1); console.log("exec2:",rs_exec2); console.log("exec3:",rs_exec3); console.log("exec4:",rs_exec4);replace使用
正則表達式構造函數:new RegExp("pattern"[,"flags"]);
正則表達式替換變量函數:stringObj.replace(RegExp, replace Text);
//下面的例子用來獲取url的兩個參數,并返回urlRewrite之前的真實Url var reg=new RegExp("(http://www.qidian.com/BookReader/)(d+),(d+).aspx","gmi"); var url="http://www.qidian.com/BookReader/1017141,20361055.aspx"; //方式一,最簡單常用的方式 var rep=url.replace(reg,"$1ShowBook.aspx?bookId=$2&chapterId=$3"); console.log(rep); // http://www.qidian.com/BookReader/ShowBook.aspx?bookId=1017141&chapterId=20361055 //方式二 ,采用固定參數的回調函數 var rep2=url.replace(reg,function(m,p1,p2,p3){ console.log("mmmm => ", m, p1,p2,p3) return p1+"ShowBook.aspx?bookId="+p3+"&chapterId="+p3 }); alert(rep2); //方式三,采用非固定參數的回調函數 var rep3=url.replace(reg,function(){var args=arguments; return args[1]+"ShowBook.aspx?bookId="+args[2]+"&chapterId="+args[3];}); alert(rep3); //方法四 //方式四和方法三很類似, 除了返回替換后的字符串外,還可以多帶帶獲取參數 var bookId; var chapterId; function capText() { var args=arguments; bookId=args[2]; chapterId=args[3]; return args[1]+"ShowBook.aspx?bookId="+args[2]+"&chapterId="+args[3]; } var rep4=url.replace(reg,capText); alert(rep4); alert(bookId); alert(chapterId); //使用test方法獲取分組 var reg3=new RegExp("(http://www.qidian.com/BookReader/)(d+),(d+).aspx","gmi"); reg3.test("http://www.qidian.com/BookReader/1017141,20361055.aspx"); //獲取三個分組 console.log(RegExp.$0) console.log(RegExp.$1); // http://www.qidian.com/BookReader/ console.log(RegExp.$2); // 1017141 console.log(RegExp.$3); // 20361055參考文檔
探究js正則匹配方法:match和exec
正則表達式30分鐘入門教程
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98529.html
摘要:遵循特定規則,利用操作符,終止節點和其他非終止節點,構造新的字符串非終結符是表示字符串的樹的內部節點。語法中的生產具有這種形式非終結符終結,非終結符和運算符的表達式語法的非終結點之一被指定為根。 大綱 基于狀態的構建 基于自動機的編程 設計模式:Memento提供了將對象恢復到之前狀態的功能(撤消)。 設計模式:狀態允許對象在其內部狀態改變時改變其行為。 表驅動結構* 基于語法的構...
摘要:想閱讀更多優質文章請猛戳博客一年百來篇優質文章等著你正則表達式或用于匹配字符串的各個部分下面是我創建正則表達式的備忘單。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 正則表達式或regex用于匹配字符串的各個部分 下面是我創建正則表達式的備忘單。 匹配正則 使用 .test() 方法 let testString = My test string; let t...
摘要:所以我們整理了一個應用安全備忘錄,以幫助你在部署啟動應用程序的時候進行安全檢查。這可以保護應用程序不被攻擊。應該用日志記錄下來,而不是顯示給用戶。 本人的博客http://www.wjs.photo/,感興趣的可以看看哦,基于NodeJs框架ThinkJs 本文翻譯自 www.risingstack.com ,并非逐字逐句的翻譯,有錯誤的地方請指出,謝謝啦 應用程序的安全就像是你房間里...
閱讀 1619·2023-04-25 14:12
閱讀 1085·2021-08-27 16:24
閱讀 2542·2019-08-30 15:44
閱讀 2921·2019-08-30 13:16
閱讀 1673·2019-08-29 14:10
閱讀 972·2019-08-29 13:54
閱讀 1306·2019-08-29 13:09
閱讀 1814·2019-08-26 18:37