日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

正则表达式从基础到深入实战

發布時間:2025/3/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 正则表达式从基础到深入实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正則表達式從基礎到深入實戰

什么是正則?

正則就是一個規則,用來處理**字符串**的規則 1、正則匹配 編寫一個規則,驗證某個字符串是否符合這個規則,正則匹配使用的是 test 方法

2、正則捕獲 編寫一個規則,在一個字符串中把符合規則的內容都獲取到,正則捕獲使用的方法:正則的exec方法、字符串中的split、replace、match等方法都支持正則

var reg = /^$/; //=>兩個斜杠中間包含一些內容就是正則,兩個斜杠之間包含的全部內容都是元字符 復制代碼

正則的元字符和修飾符

任何一個正則都是由 元字符 和 修飾符 組成的

修飾符 g(global):全局匹配 i(ignoreCase):忽略大小寫匹配 m(multiline):多行匹配

元字符 [量詞元字符] +:讓前面的元字符出現一到多次 ?:出現零到一次 *:出現零到多次 {n}:出現n次 {n,}:出現n到多次 {n,m}:出現n到m次

[特殊意義的元字符] \:轉義字符(把一個普通字符轉變為有特殊意義的字符,或者把一個有意義字符轉換為普通的字符) .:除了\n(換行符)以外的任意字符 \d:匹配一個0~9之間的數字
\D:匹配任意一個非0~9之間的數字(大寫字母和小寫字母的組合正好是反向的) \w:匹配一個 0~9或字母或_ 之間的字符 \s:匹配一個任意空白字符 \b:匹配一個邊界符 x|y:匹配x或者y中的一個 [a-z]:匹配a-z中的任意一個字符 [^a-z]:和上面的相反,匹配任意一個非a-z的字符 [xyz]:匹配x或者y或者z中的一個字符 [^xyz]:匹配除了xyz以外的任意字符 ():正則的小分組,匹配一個小分組(小分組可以理解為大正則中的一個小正則) ^:以某一個元字符開始 $:以某一個元字符結束 ?::只匹配不捕獲 ?=:正向預查 ?!:負向預查 ......

除了以上特殊元字符和量詞元字符,其余的都叫做普通元字符:代表本身意義的元字符

元字符詳細解讀

^ $

var reg = /\d+/; //=>包含某某某即可,這里說明包含1到多個數字即可 var str = '正則匹配2018'; reg.test(str) =>truereg=/^\d+/; reg.test(str) =>falsereg=/^\d+$/;//=>只能是某某某的,這里說明只能是1到多個數字 reg.test('2017'); =>true reg.test('2017正則2018'); =>false reg.test('2'); =>true ^或者$只是一個修飾或者聲明,不會占據字符串的位置 復制代碼

\

var reg = /^2.3$/; reg.test('2.3'); =>true reg.test('2+3'); =>true 點在正則中的意思:匹配除了\n以外的任意字符,而不是單純的小數點reg = /^2\.3$/; reg.test('2.3'); =>true reg.test('2+3'); =>false 使用轉義字符把點轉換為本身小數點的意思 復制代碼

x|y

var reg = /^18|19$/;//=>18 19 189 119 819 181 1819 ... 很多都符合這個規則 /** 18或者19* 以1開頭 以9結尾 中間是8或者1 * 以18開頭或者以19結尾即可 =>'18珠峰' '珠峰19'...*/var reg = /^(18|19)$/;//=>此時只有18或者19符合我們的規則了 復制代碼

():正則中的分組,也可以理解為一個大正則中的一個正則(包起來的部分是一個整體);在正則中我們可以使用小括號改變一些默認的優先級;

小分組還有第二個作用:分組引用 小分組的第三個作用:分組捕獲

//=>分組引用:\1 或者 \2 ...出現和第N個分組一模一樣的內容 var reg = /^([a-z])([a-z])\2([a-z])$/; //=> 符合的字符串:foot、book、week、attr、http... 復制代碼

[]

[xyz] [^xyz] [a-z] [^a-z]

//=>\w:數組字母下劃線中的任意一個字符 var reg = /^[a-zA-Z0-9_]$/; //=>等價于\w//=>中括號中出現的元字符,一般都代表本身的含義 var reg = /^[.?+&]+$/; //=>里面的四個元字符都是本身含義,例如:點就是小數點了,不是所謂的任意字符...//=>需求:描述樣式類名的規則(數字、字母、下劃線、-),并且不能以-開頭 //var reg = /^[\w-]+$/; //var reg = /^[0-9a-zA-Z_-]+$/; //=>沒有處理以-開頭的情況 var reg = /^\w[\w-]*$/; 復制代碼//=>需求:驗證18~65之間的年齡 //var reg = /^[18-65]$/; //=>1或者8~6或者5中的任意一個字符,中括號中出現的18不是數字18,而是1或者8,當前正則是非法的:因為不能設置8~6這種范圍//=>分三個階段處理: // 18 或者 19 /(18|19)/ // 20 ~ 59 /([2-5]\d)/ // 60 ~ 65 /(6[0-5])/ var reg = /^((18|19)|([2-5]\d)|(6[0-5]))$/; 復制代碼

常用的正則表達式編寫

驗證是否為有效數字

/** 可能是正數,可能是負數 12 -12* 整數或者小數 0 12 0.2 12.5 -12.3* 只要出現小數點,后面至少要跟一位數字* 小數點前面必須有數字*/ var reg = /^-?(\d|([1-9]\d+))(\.\d+)?$/; /** -? 負號可有可無* (\d|([1-9]\d+))* \d 一位數可以是任何值* ([1-9]\d+) 多位數不能以零開頭* (\.\d+)? 小數部分可有可無,有的話點后面必須跟一位數字*/ 復制代碼

手機號碼

/** 11位數字* 1開頭*/ var reg = /^1\d{10}$/; 復制代碼

用戶名:真實姓名

//=>/^[\u4E00-\u9FA5]$/ 中文漢字的正則 var reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10})?$/; 復制代碼

郵箱

var reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/; /** 以數字字母下劃線開頭* @前面可以是 數字、字母、下劃線、-、. 這些符號* 不能把 -和. 連續出現,出現一次后面必須跟數字字母下劃線* * @后面的部分支持* 企業郵箱* .com.cn 多域名情況*/ // [A-Za-z0-9]+ // ((\.|-)[A-Za-z0-9]+)* // \.[A-Za-z0-9]+ // @163.com.cn // @chen-wan-jun.com.cn 復制代碼

身份證號碼

/** 18位* 前17位必須是數字* 最后一位可以是數字或者X(X代表數字10)* * 371426198806064414* 前六位:省市縣 371426* 接下來八位 出生年+月+日* 倒數第二位數字 奇數代表男 偶數代表女*/ var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/; //=>這樣寫不僅可以匹配,而且以后捕獲的時候,不僅可以把大正則匹配的結果捕獲到,里面每一個小分組(小正則)匹配的結果也可以單獨的捕獲到 “分組捕獲”//=>年 1950~2017 //=>第一段 1950~1999 //=>第二段 2000~2017 //==> 00~09 //==> 10~17 // /^((19[5-9]\d)|(20((0\d)|(1[0-7]))))$/ 復制代碼

正則捕獲

把當前字符串中符合正則的字符捕獲到 RegExp.prototype:exec 實現正則捕獲的方法

var str = '正則匹配2017揚帆起航2018'; var reg = /\d+/;reg.exec(str); /** 當正則捕獲的時候:* 1、先去驗證當前字符串和正則是否匹配,如果不匹配返回的結果是null(沒有捕獲到任何的內容)* 2、如果匹配,從字符串最左邊開始,向右查找到匹配的內容,并且把匹配的內容返回* * exec捕獲到結果的格式:* -> 獲取的結果是一個數組* -> 數組中的第一項是當前本次大正則在字符串中匹配到的結果* -> index:記錄了當前本次捕獲到結果的起始索引* -> input:當前正則操作的原始字符串* -> 如果當前正則中有分組,獲取的數組中,從第二項開始都是每個小分組,本次匹配到的結果(通過exec可以把分組中的內容捕獲到)* * 執行一次exec只能把符合正則規則條件中的一個內容捕獲都,如果還有其它符合規則的,需要在次執行exec才有可能捕獲到*/ 復制代碼

正則捕獲存在懶惰性

執行一次exec捕獲到第一個符合規則的內容,第二次執行exec,捕獲到的依然是第一個匹配的內容,后面匹配的內容不管執行多少次exec都無法捕獲到

解決正則捕獲的懶惰性: 在正則的末尾加修飾符g(全局匹配)

//=>正則為什么會存在懶惰性? /** 正則本身有一個屬性:lastIndex(下一次正則在字符串中匹配查找的開始索引)* 默認值:0,從字符串第一個字符開始查找匹配的內容* 默認不管指定多少遍exec方法,正則的lastIndex值都不會變(也就是第二次以后查找的時候還是從第一個字符找,所以找到的結果永遠都是第一個匹配的內容)* 而且當我們手動把 lastIndex 進行修改的時候,不會起到任何的作用 *///=>為什么加修飾符g就解決了懶惰性? /* * 加了修飾符g,每一次exec結束后,瀏覽器默認會把lastIndex值進行修改,下一次從上一次結束的位置開始查找,所以可以得到后面匹配的內容了*/var reg = /\d+/g; var str = '正則匹配2017楊帆起航2018'; console.log(reg.lastIndex);//=>0 console.log(reg.exec(str)[0]);//=>'2017'console.log(reg.lastIndex);//=>8 console.log(reg.exec(str)[0]);//=>'2018'console.log(reg.lastIndex);//=>16 console.log(reg.exec(str));//=>nullconsole.log(reg.lastIndex);//=>0 console.log(reg.exec(str)[0]);//=>'2017' 復制代碼

exec有自己的局限性:執行一次exec只能捕獲到一個和正則匹配的結果(即使加了修飾符g),如果需要都捕獲到,我們需要執行N次exec方法才可以

下面封裝的myExecAll方法,目的是執行一次這個方法,可以把當前正則匹配到的全部內容都捕獲到

RegExp.prototype.myExecAll = function myExecAll() {var str = arguments[0] || '',result = [];//=>首先判斷THIS是否加了全局修飾符G,如果沒有加,為了防止下面執行出現死循環,我們只讓其執行一次EXEC即可,把執行一次的結果直接的返回if (!this.global) {return this.exec(str);}var ary = this.exec(str);while (ary) {result.push(ary[0]);ary = this.exec(str);}return result; };var reg = /\d+/g; console.log(reg.myExecAll('正則2017匹配2018楊帆2019起航2020')); 復制代碼

使用字符串方法match實現捕獲

var reg = /\d+/g; var str = '正則2017匹配2018楊帆2019起航2020'; str.match(reg); //=>["2017", "2018", "2019", "2020"] 復制代碼

使用字符串match捕獲: 1、如果正則加了修飾符g,執行一次match會把所有正則匹配的內容捕獲到 2、如果沒有加修飾符g,執行一次match只能把第一個匹配的結果捕獲到

局限性: 在加了修飾符g的情況下,執行match方法只能把大正則匹配的內容捕獲到,對于小分組捕獲的內容方法給其自動忽略了

var str = 'my name is {0},i am {1} years old~,2017'; //=>需求:把{n}整體捕獲到,而且還要把括號中的數字也獲取到 var reg = /\{(\d+)\}/g;// str.match(reg);//=>["{0}", "{1}"] //=>想要獲取小分組中的內容,我們只能使用EXEC處理了 function fn(reg,str){var ary=reg.exec(str),result=[];while(ary){result.push(ary);ary=reg.exec(str);}return result; } 復制代碼

使用test也可以實現正則的捕獲

不管是正則的匹配還是正則的捕獲,在處理時候的原理是沒區別的:從字符串的第一個字符向后查找,找到符合正則規則的字符,如果可以找到,說明正則和字符串匹配(test檢測返回true、exec捕獲返回捕獲的內容),如果找到末尾都沒有匹配的,說明正則和字符串不匹配(test檢測返回false、exec捕獲返回null)

如果正則設置了修飾符g,不管使用test還是exec中的任何方法,都會修改lastIndex值(下一次查找是基于上一次匹配結果的末尾開始查找的)

//=>如果當前字符串和正則是匹配的,我們進行捕獲 var reg = /\{(\d+)\}/g; var str = 'my name is {0}~~'; if (reg.test(str)) {//=>reg.test(str) : trueconsole.log(reg.lastIndex);//=>14console.log(reg.exec(str));//=>null }var reg = /\{(\d+)\}/; var str = 'my name is {0}~~'; if (reg.test(str)) {//=>reg.test(str) : trueconsole.log(reg.lastIndex);//=>0console.log(reg.exec(str));//=>['{0}','0'...] } 復制代碼

使用test不僅可以找到匹配的內容,也能像exec一樣把找到的內容獲取到 test返回結果是 true/false,所以靠返回結果肯定不行

var reg = /\{(\d+)\}/g; var str = 'my name is {0}~~,i am {1} years old~~'; reg.test(str);//=>true console.log(RegExp.$1);//=>0 獲取到當前本次匹配內容中第一個小分組捕獲的內容reg.test(str);//=>true console.log(RegExp.$1);//=>1 TEST可以實現捕獲,但是每一次只能獲取到當前本次匹配結果中,第N個分組捕獲的內容 $1第一個分組 $2第二個分組 ... 復制代碼

所有支持正則的方法都可以實現正則的捕獲(一般都是字符串方法)

字符串中常用的支持正則的方法: match split replace ...

var str = 'name=正則&age=8&lx=teacher'; str.split(/&|=/); //=>["name", "正則", "age", "8", "lx", "teacher"]str.split(/(&|=)/); //=>["name", "=", "正則", "&", "age", "=", "8", "&", "lx", "=", "teacher"]//=>在使用split進行字符串拆分的時候,如果正則中包含小分組,會把小分組中的內容都捕獲到,放在最后的數組中//=>本案例中的小括號僅僅是為了實現 改變默認的優先級 問題,但是我們不想把分組中的內容捕獲到 => “只想匹配不想捕獲” 我們可以使用 (?:) str.split(/(?:&|=)/); //=>["name", "珠峰", "age", "8", "lx", "teacher"]//=>只匹配不捕獲: //在當前一個分組中加了 ?: ,在正則檢測匹配的時候,小分組可以起到自己應有的作用(例如:改變優先級...),但是在捕獲的時候,遇到帶?:的小分組,瀏覽器不會把當前這個分組中匹配的內容,單獨去捕獲了var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(\d|X)$/; reg.exec(''); //=>["371426198806064414", "371426", "1988", "06", "06", "44", "1", "4"...]var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(?:\d{2})(\d)(?:\d|X)$/; reg.exec('371426198806064414');//=> ["371426198806064414", "371426", "1988", "06", "06", "4"...]var reg = /^-?(\d|([1-9]\d+))(\.\d+)?$/;//=>計算是第幾個分組的時候,我們從左向右找 ( 即可 復制代碼

replace

replace:字符串中原有字符的替換 str.replace(old,new)

var str = '正則2017正則2018'; str = str.replace('正則','正則匹配'); str = str.replace('正則','正則匹配'); //=>'正則匹配匹配2017正則2018' 沒有實現我們希望的效果//=>在不使用正則的情況下,執行一次replace只能替換一個原有字符,第二次執行replace,還是從字符串的開始位置查找,把最新找到的字符替換為新字符(類似于正則捕獲時候的懶惰性:每一次執行都是從字符串最開始的位置查找) 復制代碼

真實項目中,replace一般都是和正則搭配在一起使用的

var str = '正則2017正則2018'; str = str.replace(/正則/g,'正則匹配'); //=>"正則匹配2017正則匹配2018" 復制代碼

replace原理: 1、當replace方法執行,第一項傳遞一個正則 正則不加g:把當前字符串中第一個和正則匹配的結果捕獲到,替換成新的字符 正則加g:把當前字符串中所有和正則匹配的內容都分別的捕獲到,而且每一次捕獲,都會把當前捕獲的內容替換為新字符

2、當replace方法執行,第二個參數傳遞的是一個函數(回調函數) 首先用正則到字符串中進行查找匹配,匹配到一個符合規則的,就把傳遞的函數執行一次 不僅執行這個函數,而且還把正則本次捕獲的結果(和執行exec捕獲的結果一樣:數組、大正則匹配、小分組匹配 都有)當做實參傳遞給這個函數(這樣就可以在函數中獲取這些值:而這些值就是正則每一次捕獲的結果 )

var str = 'my name is {0},i am {1} years old,i can {2}!'; var reg = /\{(\d+)\}/g; str.replace(reg, function () {//=>傳遞的函數一共被執行三次//=>console.log(arguments) 每一次匹配捕獲到結果,不僅把這個方法執行了,而且還會把當前捕獲的結果當做實參傳遞給這個函數(ARG)/** 第一次執行函數,獲取的是ARG類數組* 0:'{0}' 本次大正則匹配的結果* 1:'0' 本次第一個小分組匹配的結果* 2:11 本次大正則匹配結果在字符串中的索引 index* 3:'my nam...' 原始字符串 input** 和每一次執行exec實現捕獲的結果非常類似*///return xxx;//=>每一次執行函數,函數中RETURN的結果,都相當于把本次大正則匹配的內容替換掉(原始字符串不變) }); 復制代碼

總結

以上是生活随笔為你收集整理的正则表达式从基础到深入实战的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。