正則表達式(簡單到高級)
正則表達式,又稱正規表示法、常規表示法(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在很多文本編輯器裏,正則表達式通常被用來檢索、替換那些符合某個模式的文本。
其實每個語言的正則表達式都比較苟同。
js正則表達式
正則表達式對象
一、對象:
正則表達式書寫的兩種風格perl和js(都可以在js中使用),pattern表示需要匹配的規則,其中flags表示的參數:
- g (全文查找出現的所有 pattern)
- i (忽略大小寫)
- m (多行查找)
perl風格:
#pattern-規則
#flags-參數
var reg = /pattern/[flags]
js風格
//pattern-規則
//flags-參數
var reg = new RegExp("pattern",["flags "])
二、方法
test()
返回一個 Boolean 值,它指出在被查找的字符串中是否存在模式。
字如其名,意思是測試,返回True或者false。
//字符串
var str="abc def abc def";
//正則表達式
var reg=/a/gi;
//彈出測試的真值
alert(reg.test(str))
exec()
用正則表達式模式在字符串中運行查找,並返回包含該查找結果的一個數組。可以通過循環挨個取出。
1、測試
//字符串
var str="abc def abc def";
//正則表達式
var reg=/a/gi;
//循環取出匹配到的字符a
while((r=reg.exec(str))!=null){
document.write(r+"<br/>");
}
2、一個大坑之下標指針
先看一個代碼:
//字符串
var str="abc def abc def";
//正則表達式
var reg=/a/gi;
//測試有無匹配,返回True
alert(reg.test(str))
//循環取出匹配到的字符串
while((r=reg.exec(str))!=null){
document.write(r+"<br/>");
}
正確結果有兩個a被打印,但結果只有一個a,這是爲什麼呢?
通過exec()的屬性找到了原因:
Index 屬性中包含了整個被查找字符串中被匹配的子字符串的位置。
//其他均不變,只有打印輸出改變
document.write(r+"的下標索引:"+r.index+"<br/>");
得到下標索引爲:8
結論:reg.test(str);在匹配字符串時,reg的下標索引到了第一個a的後面,所以下次開始的時候直接找到了第二個a。
String對象
search()/ split() / match() /replace()
search方法
返回與正則表達式查找內容匹配的第一個子字符串的位置。
//字符串
var str="abc def abc def";
//正則表達式
var reg=/def/gi;
//彈出匹配到字符串的位置
alert(str.search(reg))
//結果
4
split方法
將一個字符串分割爲子字符串,然後將結果作爲字符串數組返回。
//字符串
var str="abc def abc def";
//彈出分割後的字符
alert(str.split(" "));
//結果
abc,def,abc,def
match方法
使用正則表達式模式對字符串執行查找,並將包含查找的結果作爲數組返回。(所有符合正則表達式條件的都會返回,和search的區別之一)
//字符串
var str="abc def abc def";
//正則表達式
var reg=/def/gi;
//彈出結果
alert(str.match(reg));
//結果
def,def
replace方法
//字符串
var str="abc def abc def";
//正則表達式
var reg=/def/gi;
//彈出替換後的結果
alert(str.replace(reg,"hello"));
//結果
abc hello abc hello
元字符
在正則中代表了一個特殊的符號 ( 它代表了一個語義),如果要查找這種符號,則必須轉義.
( [ { \ ^ $ | ) ? * + .
比如需要匹配\,則需要\\
//字符串
//在字符串\'字符'表示的另外的含義,所以要加兩個\\
var str="a\\bc d\\e\\f a\\bc def";
//正則表達式
var reg=/\\/gi;
//循環輸出
while((r=reg.exec(str))!=null){
document.write(r+"的下標索引:"+r.index+"<br/>");
}
//結果
\的下標索引:1
\的下標索引:6
\的下標索引:8
\的下標索引:12
正則表達式字符
字符 | 描述 |
---|---|
. | [^\n\r],除\n\r外的其它字符 |
\d | 一個數字 |
\D | 非一個數字 |
\w | 匹配包括下劃線的任何單詞字符。等價於’[A-Za-z0-9_]’ |
\W | 匹配任何非單詞字符。等價於 ‘[^A-Za-z0-9_]’ |
\s | 匹配任何空白字符,包括空格、製表符、換頁符等等 |
\S | 匹配任何非空白字符 |
\u4e00-\u9fa5 | 中文 |
量詞
字符 | 描述 |
---|---|
? | 0或1 |
* | 0或多次 |
+ | 至少一次 |
{n} | n次 |
{n,} | 至少n次 |
{n,m} | 至少n次至多m次 |
^
1、非
[^abc]Hello
表示 Hello前不能是 a /b/c
2、行開頭 行結尾
匹配輸入字符串的開始位置和結束爲止。
匹配的是整個字符串
//字符串
var str="abc 1def 1abc def";
//正則表達式
var reg=/^[\w\s]*$/gi;
//輸出
while((r=reg.exec(str))!=null){
document.write(r+"<br/>");
}
//結果
abc 1def 1abc def
$妙用
無$:(瀏覽器會假死)
//字符串
var str="(abc 1def 1abc def";
//正則表達式 $妙用(有無$)
var reg=/^[\w\s]*/gi;
//輸出
while((r=reg.exec(str))!=null){
document.write(r+"<br/>");
}
在沒有成功匹配到結果時,有$結束則會立刻結束
分組
分組原理(exec原理):
存分組的總的結果,和裏面所包含所有元素的結果。
1、單個分組
<script>
//字符串
var str="j123in t345ian xing qi wu shi ma?";
//正則表達式
var reg=/(\d+)([a-z]+)/gi;
//輸出
while((r=reg.exec(str))!=null){
document.write("r: "+r+"<br/>");
document.write("r[0]: "+r[0]+"<br/>");
document.write("r[1]: "+r[1]+"<br/>");
document.write("r[2]: "+r[2]+"<br/>");
document.write("r[0][0]: "+r[0][0]+"<br/>");
document.write("r[1][0]: "+r[1][0]+"<br/>");
document.write("r[1][1]: "+r[1][1]+"<br/>");
document.write("r[1][2]: "+r[1][2]+"<br/>");
}
</script>
//結果
//第一個是總的匹配,第二個是總的匹配下面所有的元素
r: 123,123
r[0]: 123
r[1]: 123
r[2]: undefined
r[0][0]: 1
r[1][0]: 1
r[1][1]: 2
r[1][2]: 3
r: 345,345
r[0]: 345
r[1]: 345
r[2]: undefined
r[0][0]: 3
r[1][0]: 3
r[1][1]: 4
r[1][2]: 5
2、多個分組
<script>
//其他均未改變,只改變正則表達式
//正則表達式
var reg=/(\d+)([a-z]+)/gi;
</script>
//結果
r: 123in,123,in
r[0]: 123in
r[1]: 123
r[2]: in
r[0][0]: 1
r[1][0]: 1
r[1][1]: 2
r[1][2]: 3
r: 345ian,345,ian
r[0]: 345ian
r[1]: 345
r[2]: ian
r[0][0]: 3
r[1][0]: 3
r[1][1]: 4
r[1][2]: 5
r的長度爲3,r[0]是所有複合元素的集合,r[1],r[2]是集合中的元素,分別爲數字和字母。
3、組合分組
<script>
//其他均未改變,只改變正則表達式
//正則表達式
var reg=/((\d+)([a-z]+))/gi;
</script>
//結果
r: 123in,123in,123,in
r[0]: 123in
r[1]: 123in
r[2]: 123
r[0][0]: 1
r[1][0]: 1
r[1][1]: 2
r[1][2]: 3
r: 345ian,345ian,345,ian
r[0]: 345ian
r[1]: 345ian
r[2]: 345
r[0][0]: 3
r[1][0]: 3
r[1][1]: 4
r[1][2]: 5
通過以上的代碼瞭解到,分組其實就是把()內符合條件的都單獨存放在一個數組中,一層層包含。組合分組最大,接下來是第一個分組,第二個分組,第三個分組。。。那麼他們究竟有什麼用呢?
4、案例分析
所有的操作系統都有一個搜索功能,現在需要用js來實現查找文件後綴爲doc的文檔。
<script>
var str="test01.doc,test02.doc,js_01.txt,js_02.txt,web01.html,web02.html";
var reg=/(\w+)\.([a-z]+)/gi;
//輸出
while((r=reg.exec(str))!=null){
document.write("r: "+r+"<br/>");
if(r[2]=="doc"){
document.write("所有doc文檔的名字:"+r[1]+"<br/>");
}
}
</script>
//結果
所有doc文檔的名字:test01
所有doc文檔的名字:test02
5、總結
分組是一個很重要而且很常見的使用。需要重點掌握。
候選
1、( | )
<script>
//字符串
var str="done is better 2015";
//正則表達式
var reg=/(\w+|\d+)/gi;
//輸出
while((r=reg.exec(str))!=null){
document.write(r+"<br/>");
}
</script>
//結果
done,done
is,is
better,better
2015,2015
還是分組,|意爲或
2、[ | ]
<script>
//其他均未改變,只改變正則表達式
//正則表達式
var reg=/[\w+|\d+]/gi;
</script>
//結果
d
o
n
e
i
s
b
e
t
t
e
r
2
0
1
5
沒有進行分組,每次都是輸出一個單個的字符。
反向引用
表達式計算完的每個分組(按照括號從左到右的順序)被存儲在RegExp構造函數中,通過$n獲取。
<script>
//字符串
var str="123 is 456 2015";
//正則表達式
var reg=/(\d+)/gi;
//必須先執行一次正則表達式,執行完後,正則表達式中一個數組中存儲了滿足條件的值
reg.test(str);
//輸出
document.write(RegExp.$1);
</script>
//結果
123
(?:分組條件)
在分組時,捕獲到數據後,不做存儲.。
匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以後使用。這在使用 “或” 字符 (|) 來組合一個模式的各個部分是很有用。例如, ‘industr(?:y|ies) 就是一個比 ‘industry|industries’ 更簡略的表達式。
<script>
//字符串
var str="dona is donb 2015";
//正則表達式
var reg=/don(?:a|b)/gi;
//輸出
while((r=reg.exec(str))!=null){
document.write(r+"<br/>");
}
</script>
//結果
dona
donb
js正則表達式的幾個案例:
1、反向引用
<script>
//字符串
var str="1-張三,2-李四,3-王五";
//正則表達式
var reg2=/(\d)+-([\u4e00-\u9fa5]+)?/gi;
//反向顯示這個字符
document.write(str.replace(reg2,"$2-$1"));
</script>
//結果
張三-1,李四-2,王五-33
<script>
//字符串
var str="湘C22222 湘D33333 湘C44444 湘C55555 湘C66666 湘C77777 湘C88888 湘C12345 湘C34445";
//正則表達式 靚牌
//匹配後面爲重複數字的車牌
var Reg1=/([\u4e00-\u9fa5]\w(\d{1})\2{4})/gi;
document.write(str.match(Reg1));
</script>
//結果
湘C22222,湘D33333,湘C44444,湘C55555,湘C66666,湘C77777,湘C88888
2、候選,可用來對網頁內容樣式的選擇
<script>
var s1="red";
var s2="black";
//字符串候選
var rorb=/(red|black)/;
document.write(rorb.test(s1)+"<br/>");
document.write(rorb.test(s2)+"<br/>");
var str="red is a color,black is another color";
//字符候選
var reg=/[red|black]/gi;
document.write(str.match(reg));
</script>
//結果
true
true
r,e,d,a,c,l,r,b,l,a,c,k,a,e,r,c,l,r
3、分組 對數據的一個校正
<script>
//舊圖書編號5位數字 新圖書編號5位數字-4位編號
var bookbsn="10101,10102,10103-0001,10104-0002,10104-0003";
//分成三組
var reg=/(\d{5})(-(\d{4}))?/gi;
bookbsn.match(reg);
var index=0;
var i;
var arr=new Array();
//分組 第一組:(\d{5}) 第二組加- 第三組不加-
//
while((r=reg.exec(bookbsn))!=null){
if(r[2]==null||r[2]==''){
arr[index++]=r[1];
}else{
arr[index++]=r[3];
}
}
document.write(arr);
</script>
//結果
10101,10102,0001,0002,0003
總結
javascript是一門很“活潑”的語言,駕馭的好可以做出很多有趣,很方便的東西,正則表達式相對於java,python來說,js更難一點。
通過js我們可以快速的驗證一個用戶名,密碼,重複密碼,電話號碼,區號,郵箱,地址等等格式正確與否,不需要通過和服務器進行交換數據,就能很方便的校驗,一個可以減少數據庫的壓力,另一方面可以提高用戶體驗,實乃神器。