對於正則表達式的一些整理

對於正則表達式,以前開發都靠強大的百度。論正則的規矩,看見奇怪的符號,每每不讓人選擇放棄。之所以學習,是發現找到一個合適的正則是多麼難的一件事,若要在人家的基礎上去修改,卻又看不懂這些個火星文,不得不感嘆,還是自食其力的好。

本篇文章是筆者對於正則表達式學習的整理,適合與筆者一樣,剛剛認真去學習正則表達式的人,若有較熟悉者,歡迎指正。

一、字符串組成類型
正則表達式由兩種字符類型組成:

  1. 原義文本字符
  2. 元字符

原義文本字符。類似於像abc,123
元字符。在正則表達式中有特殊含義的非字母字符,類似於 /b

用的都比較特殊的,例如* + ? $ ^ . | \ () {} [],可以通過下圖查找。
菜鳥教程還蠻詳細的:https://www.runoob.com/regexp/regexp-metachar.html
在這裏插入圖片描述
這裏說說我試的幾個。
(1) [ ] 用來構建一個簡單的類
比如說,/[abc]/g,這種屬於一類,相當於或的關係,只要是滿足了其中一個條件,即觸發相應的操作。
如果用這個正則表達式去匹配
eg: ‘He is a boy. This is a dog. where is she’.replace(/[abc]/g, ‘AB’);
// “He is AB ABoy. This is AB dog. where is she”

(2)^ ,一般是指[^ ] 用來創建反向類/負向類****
仍然是上面那個例子,加 ^變成了
eg: ‘He is a boy. This is a dog. where is she’.replace(/[^abc]/g, ‘AB’);
// “ABABABABABABaABbABABABABABABABABABABABABaABABABABABABABABABABABABABABABABABAB”

範圍類:當我們說要匹配一個類的時候,比如說A-Z的26個字母,可以使用[A-Z]來連接兩個字符表示從a到z的任意字符。
[] 組成的類內部是可以連寫的 比如 /[a-zA-Z]/g;
比如想匹配數字和橫線,或斜線 [a-z]表示一個範圍,但是如果想匹配-,直接在[0-9-]加一個"-"就好了。

(3) 預定義類
個人感覺到這像是一個語法糖,可以根據自己的所需去匹配所有希望匹配的字符串。
在這裏插入圖片描述
根據圖上的符號,我們可以匹配合適的字符串
例如:匹配一個 ab + 數字 + 任意字符的 字符串
這個可以自己去匹配查找對應的一些預定義類
/ab\d./
‘He is a boy. This is a dog. ab993, qe’.replace(/ab\d./, ‘帥’);
// “He is a boy. This is a dog. 帥3, qe”

(4)邊界
還是相當於預定義類,只是規定了何時開始,何時結束,用來約束當某一個條件時,才觸發相應的規則。
eg;‘This is a boy’.replace(/is/g, ‘0’)
// Th0 0 a boy
‘This is a boy’.replace(/\bis\b/g, ‘0’)
// This 0 a boy
‘This is a boy’.replace(/\Bis\b/g, ‘0’)
// Th0 is a boy

還有的元字符,並不只有一個意思,在特定的內容中代表不同的含義。
比如 * ,是以xxxx開始,而 $ 是以xxx結束。 還有 \B與\b
‘@123@abcA@’.replace(/@./g, ‘Q’);
//Q23QbcA@ --@後匹配任意字符
‘@123@abcA@’.replace(/^@./g, ‘Q’);
//“Q23@abcA@” --以@開頭的字符串
‘@123@abcA@’.replace(/.@/g,Q);//"@123@abcQ"/g, 'Q'); //"@123@abcQ" --以xx結束

還有類似m,是用來處理換行的
比如
"X23
@456
@789
"
/^@\d/gm/ 後綴加個m,就是用來處理換行的

(5) 量詞
在這裏插入圖片描述
比如說,我們希望匹配一個連續出現20次數字的字符串
\d\d\d\d…這樣連續寫20遍顯然很變態,於是就出現了,專門的量詞,來匹配符合條件的字符串
一般的使用場景,會去匹配輸入了多少次,限制表單的大小。
? + * {n} {n,m} {n,}

(6) 貪婪模式
儘可能多的匹配,如果匹配失敗了再記性後續的操作。
‘12345678’.replace(/\d{3,6}/g, ‘X’);
// “X78”

(7) 非貪婪模式
儘可能少的少用,如果匹配成功了就不繼續了
知識的關鍵點: 在量詞後面加?

好了,到了後面已經稍稍加深了。從這裏起,我就分爲了第二部分,畢竟邏輯已經漸漸加深了。

二、帶有邏輯的正則
(1) 分組
場景:匹配字符串repeat連續出現3次的場景
比如這麼寫 repeat{3} 但是呢,這個意思是說,t出現3次
使用()可以達到分組的功能,是量詞作用於分組
比如’a1b2c3d4’
滿足字母加數字出現三次的,就觸發條件
‘a1b2c3d4’.replace(/([a-z]\d){3}/g, ‘x’);
// xd4

(2)或
使用 | 達到效果
ti(ng|ti)ng
‘tingting’.replace(/ting|ting/g, ‘X’);
// XX
如果只想要局部換,那麼
‘tingting’.replace(/tin(g|t)ing/g, ‘X’);

(3)反向引用
比如說,要把年月日2016-11-25替換成11/23/2016
我能想到的,就是用正則表達式把他給匹配出來。
比如說:/\d{4}-\d{2}-\d{2}/g,這其實是第一步,把表達式按正向理出來,可是有一個問題,我們不知道後綴如何替換,也就是
我們並不能動態獲取,2016,11,25具體是哪年,哪月,哪日。
這是時候學會了一個東西就是 $ 符號,$符合配合()分組,可以捕獲()裏的內容
‘2018-03-02’.replace(/(\d{4})-(\d{2})-(\d{2})/g, ‘$2/$3/$1’);
//“03/02/2018”

(4)忽略分組
不希望捕獲某些分組,只需要在分組內加上 ?:就可以

(5)前瞻後顧
正則表達式從文本頭部向尾部開始解析,文本尾部方向,則是"前"
前瞻就是在正則表達式匹配到規則的時候,向前檢查是否符合斷言,後顧/前瞻方向相反
但是js不支持後顧
符合和不符合特定斷言成爲肯定/正向匹配和否定/負向匹配
在這裏插入圖片描述
我們可以運用以上的符號來判斷前瞻後顧,具體怎麼用呢,其實就是類似於在代碼裏面添加if else判斷條件
a23.replace(/\w(?=\d)/g,‘x’);
//x2
3
其中 ?=\d 就是去判斷是不是數字,只有滿足條件的字母纔可以替換

三、一些執行方法
相信以前總被正則表達式的執行方法給整暈了。到底有哪些方法,這些方法又有什麼用,有何區別。好吧,本來應該很早就知道的東西了,就是因爲太懶了,一直沒有去整理。

執行正則表達式時,有test和exec方法。

(1)RegExp.prototype.test(str)
這個方法的目的用於測試字符串參數中是否存在匹配正則表達式模式的字符串。
通常,我們用這個方法來做頁面上的一些參數校驗,通過返回true,不通過則返回爲false。

var reg1 = /\w/
reg1.test('a');
// true

var reg1 = /\w/g;
reg1.test('a');
// true
reg1.test('a');
//false
reg1.test('a');
// true
reg1.test('a');
// false

reg1.lastIndex 當前匹配結果的最後一個字符的最後一個字符,匹配並不是從第一個開始的,會記錄每一次的過程。比如說這次是從下標爲0的地方開的,那麼下次的記錄則是從2或者是從符合條件的下標開始的。

(2)RegExp.prototype.exec(str)
使用正則表達式對字符串執行搜索,並將全局RegExp對象的屬性以反映匹配結果
如果匹配到了返回null,沒有返回一個結果數組
index --聲明匹配文本的第一個字符的位置

與test相比,他有何不同?
非全局調用下
調用非全局的RegExp對象的exec時,返回數組
第一個元素是與正則表達式相匹配的文本
第二個元素是與RegExpObject的第一個子表達式相匹配的文本
第三個元素是與RegExp對象的第二個子表達式相匹配的文本

var reg3 = /\d(\w)(\w)\d/;
var ts = "1az2bb3cy4dd5ee";
var ret = reg3.exec(ts);
console.log(reg3.lastIndex + '\t'+ret.index + '\t' + ret.toString());
// 0	0	1az2,a,z

這裏的lastIndex 對非全局無用,如果要找第一個就用非全局的。

var reg5 = /\d(\w)(\w)\d/g; --改成全局的
var ts = "1az2bb3cy4dd5ee";
var ret5 = reg5.exec(ts);
// 如果想拿到更多的值,那麼要加上
console.log(reg5.lastIndex + '\t'+ret5.index + '\t' + ret5.toString());
// 4	0	1az2,a,z

4是怎麼來的? 我們按laz2 bb3cy類似這樣去分組,lastIndex當前匹配的下一個字符是b,所以輸出的是4
index是當前匹配的
laz2是匹配的分組,按z,2進行的分組

四、和正則表達式相關的一些字符串對象方法
(1) String.prototype.search()
–用於檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串
–返回第一個匹配結果index,差不多返回-1
–不執行全局匹配,忽略標誌g,並且總是從字符串的開始進行檢索
‘aa’.search(‘1’) // -1
‘aa’.search(’/1/’) // -1

(2)String.prototype.match(reg);
作用:
1.檢索字符串,以找到一個或多個與regexp匹配的文本
2.regexp是否具有標誌g對結果影響很大

非全局下
只在字符串中執行一次匹配
沒有找到返回null,找到了返回一個數組

返回數組的第一個元素存放的是匹配文本,而其餘的元素存放的是與正則表達式的子表達式匹配的文本
除了常規的數組元素之外,返回的數組還含有2個對象屬性
index 聲明匹配文本的起始字符在字符串的位置
input 聲明對stringObject的引用

全局調用下
如果regexp 具有標誌g則進行全局檢索,找到字符串中的所有匹配子字符串
–沒有找到匹配的子串,則返回null
–如果找到了一個或多個匹配子串,則返回一個數組
數組元素每項都是匹配子串,沒有什麼input屬性

var reg5 = /\d(\w)(\w)\d/g; --改成全局的
var ts = "1az2bb3cy4dd5ee";
var ret5 = ts.match(reg5);
//  ["1az2", "3cy4"]

(3) String.prototype.split(reg)
我們比較常用的場景是把字符串弄成’,'分割成數組
對於比較複雜的字符串,實際可以傳入正則表達式,進行分割

'a1b2c3d4e'.split(/\d/g);
//  ["a", "b", "c", "d", "e"]

(4) String.prototype.replace(reg)
–找誰,替換誰
replace有兩個入參,第一個可以是字符,也可以是正則表達式
replace(reg, function)
funtion這裏是一個回調函數,有四個入參
1.匹配字符串
2.正則表達式分組內容,沒有分組則沒有該參數
3.匹配項在字符串中的index
4.原字符串
例如:'a1b2c3d4e5’想要把這個字符串中的數字都加1
var str = ‘a1b2c3d4e5’;
str.replace(/\d/g, function(match, index, str){
return parseInt(match) + 1;
})

最後一個環節,我要添加一下,常用的正則表達式,給我自己學習學習。畢竟還是要多多聯繫嘛。從github上貼來,這篇文章也講得很不錯https://github.com/cdoco/learn-regex-zh star一下,算是小白的啓蒙課程了。

正整數: ^\d+$
負整數: ^-\d+$
電話號碼: ^+?[\d\s]{3,}$
電話代碼: ^+?[\d\s]+(?[\d\s]{10,}$
整數: ^-?\d+$
用戶名: ^[\w\d_.]{4,16}$
字母數字字符: ^[a-zA-Z0-9]*$
帶空格的字母數字字符: ^[a-zA-Z0-9 ]*$
密碼: ^(?=^.{6,}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$
電子郵件: ^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})*$
IPv4 地址: ^((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))*$
小寫字母: ^([a-z])*$
大寫字母: ^([A-Z])*$
網址: ^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$
VISA 信用卡號碼: ^(4[0-9]{12}(?:[0-9]{3})?)*$
日期 (MM/DD/YYYY): ^(0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2}$
日期 (YYYY/MM/DD): ^(19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])$
萬事達信用卡號碼: ^(5[1-5][0-9]{14})*$
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章