標籤:方式 表達 [] 相關 多行 取反 Regex文法 種類 ase
Regex(英文:regular expression),是一種符合某種文法規則的文本。同時可以理解為使用單個字串來描述,匹配一系列的符合某種文法規則的字串。許多語言都有著符合自己文法規範的Regex,如java,python,php,js。雖然這些正則不是完全一樣,但也是大同小異。今天我想重點說的是JS中的Regex。
Regex的功能十分強大,能夠熟練掌握它能夠為平時的學習和工作帶來不少的便利。雖然正則理解入門不是很難,但是真正地去掌握它並且熟練地運用起來卻不是一件容易的事情。
學習正則有一個很好的線上的網站 https://regexper.com/ 。它可以協助你更好的理解Regex中的一些關係。
Regex基礎文法內容
1.1Regex的構造
在js中,Regex有兩種構造方式。一種是常用的字面量標記法,即將正則字串寫在/(regexp)/
例如要匹配一個數字
var reg=/\d/;
還有一種是建構函式的方法,即new RegExp()。該方法有接收兩個參數,第一個參數是正則字串,第二個是匹配的模式(下文會講)。但是第一個參數比較特殊,在逸出字元時同時要轉義逸出字元,即若是用這種方法匹配一個數字,
var reg=new RegExp(‘\\d‘,‘g‘);
1.2Regex的匹配模式
常見匹配模式有三種,即全域匹配g,不區分大小寫i,多行搜尋匹配m。
‘abcd‘.replace(/[a-z]/,‘1‘) //‘1dcd‘ 只匹配一次‘abcd‘.replace(/[a-z]/g,‘1‘) //‘1111‘ 都可以被匹配‘ABcd‘.replace(/[a-z]/,‘1‘) // ‘AB1d‘ ‘ABcd‘.replace(/[a-z]/gi,‘1‘) //‘1111‘‘abc‘.replace(/^[a-z]/,‘1‘) //‘1bc‘//分行符號隔開‘abc‘.replace(/^[a-z]/m,‘1‘) //‘111‘
2.Regex文法
2.1元字元
Regex由兩種基底字元類型組成:①.原義文本字元,就是字元本身代表的意思。如 a 匹配 a ,1匹配1 ②.元字元,即正則中有特殊含義的非字母字元 如 * + ? $ ^ . | \ () {} []
元字元構成了許多有意義的特殊字元,例如 \t 水平定位字元 \v垂直定位字元 \n分行符號 \r斷行符號符 \0Null 字元 \f換頁符
2.2字元類
一般情況下正則中一個字元匹配字串中的一個字元,但是可以用元字元[]來構建一個符合某種特性的類,即符合這種特性的字元都可以被匹配。如[a,b,c]匹配a或b或c
‘abcd‘.replace(/[abc]/g,‘d‘) //‘dddd‘ 即abc都可以被匹配
2.2.1字元類取反
使用元字元^可以建立反向類,即不屬於某種類的內容 如[^abc]匹配不是abc的字元
‘abcde‘.replace(/[^abc]/g,‘x‘) //‘abcxx‘ 即把不是abc的字元替換為x
2.2.2範圍類
可以在[]中用-來串連兩個字元表示範圍 如[a-z]相當於[abcd.....xyz],[0-9]相當於[0123456789],這樣帶來了許多便利。
在範圍類的內部可以連寫。如[a-zA-Z]匹配所有大小寫字母。如果要匹配-則要在之後加上-,在兩個字元之間的-表示範圍。
‘1970-01-01‘.replace(/[0-9]/g,‘a‘) //‘aaaa-aa-aa‘ ‘1970-01-01‘.replace(/[0-9-]/g,‘a‘) //‘aaaaaaaaaa‘
2.2.3預定義類
①.可以匹配常見的字元類.
例如 .匹配除了斷行符號符和分行符號(\r\n)之外的所有字元 ;\d([0-9])匹配數字字元,\D([^0-9])匹配非數字字元;\s([\t\n\x0B\f\r])匹配空白符,\S([^\t\n\x0B\f\r])匹配非空白符;\w([a-zA-Z_0-9])匹配單詞字元,\W([^a-zA-Z_0-9])匹配非單詞字元.
②.邊界匹配字元.如^ 表示以xxx開頭(這裡要注意區分開反向類,它在[]外,在[]內部表示取反) $表示以xxx結尾 \b表示單詞邊界 \B表示非單詞邊界。
2.3量詞
量詞表示可以匹配任意數量的字串.如?表示匹配0次或1次,+表示匹配1次或多次,*表示匹配0次或多次 ,{n}表示匹配n次,{n,m}表示匹配n次到m次,{n,}表示匹配至少n次
‘abcd‘.replace(/[a-z]?/,‘x‘) //‘xbcd‘‘abcd‘.replace(/[a-z]+/,‘x‘) //‘x‘‘abcd‘.replace(/[a-z]*/,‘x‘) //‘x‘‘abcd‘.replace(/[a-z]{2,3}/,‘x‘) // ‘xd‘以上都是在貪婪模式下匹配返回的字串,這是正則預設的匹配模式,下文會詳細說明
2.4貪婪模式與非貪婪模式.
貪婪模式是正則表示式預設的匹配模式,即儘可能多的匹配字元。非貪婪模式則相反,儘可能少的匹配,一旦匹配成功則不再嘗試。
貪婪模式如下
‘12345678‘.replace(/\d{3,6}/g,‘0‘) //‘078‘
非貪婪模式,只需在量詞後加上?就可以了。
‘12345678‘.replace(/\d{3,6}?/g,‘0‘) //‘0078‘
2.5分組
①分組表示可以將不同的正則分為一組去匹配字串。用()括起來的部分表示一個分組。如([a-z]\d)表示一個小寫字母與一個數字為一組
‘a1b2c3d4‘.replace(/([a-z]\d){3}/g,‘x‘) //‘xd4‘
②或,用 | 表示。例如
‘cathatbat‘.replace(/[c|h|b]at/g,‘x‘) // ‘xxx‘
③反向引用,在正則中很重要的一個方法.$1,$2,$3...$n表示的是分組內的內容,分組上文講過用()括起來的是一個分組,用$捕獲分組內的內容,也叫擷取的群組。
如要將1970-01-01替換成01/01/1970
‘1970-01-01‘.replace(/(\d{4})-(\d{2})-(\d{2})/g,‘$2/$3/$1‘)// 01/01/1970
④忽略分組,若不希望捕獲某些分組,只需要在分組內加上?: 就可以了
2.6前瞻後顧
前瞻就是Regex匹配到規則時,向前檢查是否符合斷言,後顧方向相反。JS中不支援後顧。
正向前瞻 exp(?=assert)
‘a2*3‘.replace(/\w(?=\d)/g,‘x‘) //‘x2*3‘
負向前瞻 exp(?!assert)
‘a2*3‘.replace(/\w(?!\d)/g,‘x‘) // ‘ax*3‘
3.RegExp對象
3.1.RegExp對象屬性
global:是否全文檢索搜尋,預設為false,唯讀
ingore case:是否大小寫敏感,預設為false,唯讀
multiline:是否多行搜尋,預設為false,唯讀
lastIndex:當前運算式匹配內容的最後一個字元的下一個字元的位置,只在全域匹配中有作用
source:Regex的文本字串
3.2.RegExp對象的相關方法
①.RegExp.prototype.test(str)
用於測試字串參數中是否存在匹配Regex模式的字串,存在返回true,不存在返回false
這裡要注意一個問題,就是關於lastIndex指向問題
var reg=/\w/g ;reg.test(‘ab‘) //第一次 返回true 沒問題reg.test(‘ab‘) //第二次 返回true 沒問題reg.test(‘ab‘) //第三次 返回false 有問題
reg.test(‘ab‘) //第四次 返回true
while(reg.test(‘ab‘)){ console.log(reg.lastIndex); }// 1 2
Regex對象每次匹配都作用在正則表示式本身,每次匹配成功都會去根據lastIndex去尋找下一個字元是否匹配,若沒有則lastIndex會被重設成0。
②.RegExp.prototype.exec(str)
使用Regex對字串執行搜尋,並將更新全域RegExp對象的屬性以反映匹配結果。如果沒有匹配的文本返回null,否則返回一個結果數組。
該結果數組中有兩個特別的對象屬性:
index:聲明匹配文本的第一個字元的位置,
input:存放匹配的字串
第一個元素是與Regex想匹配的文本
第二個元素是與RegExp對象的第一個子運算式想匹配的文本
第三個是與RegExp對象的第二個子運算式匹配的文本,以此類推
var reg1=/\d(\w)\d/;var reg2=/\d(\w)\d/g;var str=‘1a2b3c4d5e‘;reg1.exec(str) //["1a2", "a", index: 0, input:"1a2b3c4d5e"]reg2.exec(str)//["1a2", "a", index: 0, input: "1a2b3c4d5e"]
4.字串對象與正則相關的方法
①String.prototype.search(reg)
用於檢索字串中指定的子字串,或檢索與Regex相匹配的子字串
返回第一個匹配結果的index,若尋找不到則返回-1,
不執行全域匹配,忽略g標誌。
‘a1b2c3d1‘.search(/1/) //1‘a1b2c3d1‘.search(/1/g) //1 忽略g標誌
②String.prototype.match(reg)
用於檢索字串,以找到一個或多個與regexp匹配的文本,是否具有g標誌對結果影響很大
非全域調用
只執行一次匹配,沒有找到匹配文本則返回null,否則返回一個數組,其中存放了與它找到匹配文本相關的資訊。
該結果數組中有兩個特別的對象屬性:
index:聲明匹配文本的第一個字元的位置,
input:存放匹配的字串
第一個元素是與Regex想匹配的文本
第二個元素是與RegExp對象的第一個子運算式想匹配的文本
第三個是與RegExp對象的第二個子運算式匹配的文本,以此類推
這與RegExp對象的exec方法很類似,只是字串與Regex的位子互換了。
全域調用
執行全域搜尋,找到字串中的所有匹配子字串,沒有找到返回null,否則返回一個數組,其中存放了與它找到匹配文本的相關資訊。
該結果數組中有兩個特別的對象屬性:
index:聲明匹配文本的第一個字元的位置,
input:存放匹配的字串
數組中的元素存放的是字串中所有的匹配到的子字串
③String.prototype.split(reg)
split方法是我們熟悉的方法,我們經常用split將一個字串分割成一個數組,同樣的這個分割符可以是一個Regex.
‘a1b2c3d‘.split(/\d/g) //["a", "b", "c", "d"]
④.String.prototype.replace()
這個方法是特別重要也相對較複雜的方法,功能特彆強大的一個方法。
它有兩個參數,第一個參數是需要被替換的字串,第二個參數是用來替換的字串。
它有三種使用方法
String.prototype.replace(str,newStr),
String.prototype.replace(reg,newStr),
String.prototype.replace(reg,function)
重點就在於String.prototype.replace(reg,function)
function的傳回值是替換結果.這個function在每次匹配替換的時候被調用,有四個參數
1.匹配的字串
2.Regex分組內容,沒有分組則沒有該參數
3.匹配項在字串中的index
4.原字串
//沒有分組的情況
‘a1b2c3d4‘.replace(/\d/g,function(match,index,origin){ return parseInt(match)+1; })//"a2b3c4d5"
//有分組的情況
‘a1b2c3d4‘.replace(/(\d)(\w)(\d)/g,function(match,group1,group2,group3,index,origin){ return group1+group3;})//"a12c34"
以上就是Regex的大部分內容。Regex功能很強大,能熟練應用會給我們帶來很多便利。
JS之Regex