正則(Regular Expression):是一個處理字符串的規則javascript
學習正則其實就是在學習如何編寫規則,每個正則都是由元字符和修飾符兩部分組成java
let reg = /^\d+$/g;
//字面量方式let reg2 = new RegExp(''||//, 'g');
//構造函數方式 第一個參數能夠放變量經常使用的修飾符 | 全稱 | 含義 |
---|---|---|
i | ignoreCase | 忽略大小寫匹配 |
m | multiline | 多行匹配 |
g | global | 全局匹配 |
// m 修飾符 多行匹配
let str = ` 趙州橋 長江大橋 多孔橋 南浦大橋 `
let reg = /橋$/mg;
console.log(str.match(reg)); //["橋", "橋", "橋", "橋"]
複製代碼
\d
0-9之間的一個數字\D
非0-9之間的任意字符\w
數字、字母、下劃線中的的任意一個字符 /[0-9a-zA-Z_]/
\W
非數字、字母、下劃線中的任意字符\s
匹配任意一個空白字符,包括:
// test() 方法用於檢測一個字符串是否匹配某個模式.
let str = '1-7p';
let reg = /\b7p/;
console.log(reg.test(str)); //true
console.log(reg.exec(str)); //[7p...]
複製代碼
\n
匹配一個換行符 (enter)let str = 'b7\np';
let reg = /^b7\np$/;
console.log(reg.test(str)); //true
console.log(reg.exec(str)); //["b7↵p"...]
console.log(str.match(reg)); //["b7↵p"...]
複製代碼
\r
匹配一個回車符\
轉義字符: 有兩個做用
\d
;\.
此處的點不是任意字符,而是一個小數點.
不只是小數點,表明除了\n 之外的任意字符let reg = /^.$/;
console.log(reg.test('n')); //true
console.log(reg.test('1')); //true
console.log(reg.test('\n')); //false
console.log(reg.test('nn')); //false 只能是一位
複製代碼
^
以某個元字符開頭$
以某個元字符結尾x|y|z
x或者y中的任意一個(x和y是自定義的字母)[xyz]
x或者y或者z中的任意一個(xyz爲自定義)[^xyz]
非x\y\z的任意字符[a-z]
獲取a-z中的任意一個字符 [0-9] <=> \d[^a-z]
非a-z的任意字符()
正則分組(?:)
當前正則只匹配不捕獲(?=)
正向預查(?!)
負向預查*
出現0到多個字符?
出現0到1個字符+
出現1到多個字符{n}
出現n個字符{n,}
出現n到多個字符{n,m}
出現n到m個字符// *能夠出現0到屢次
let reg = /\d*/;
console.log(reg.test('')); //true
console.log(reg.test('52246')); //true
複製代碼
//+ 能夠出現1到屢次,可是不能一次都不出現
let reg = /\d+/;
console.log(reg.test('')); //false
console.log(reg.test('2')); //true
複製代碼
// ?能夠出現0-1次
let reg = /^\d?$/; //?能夠出現0-1個字符
console.log(reg.test('')); //true
console.log(reg.test('5')); //true
console.log(reg.test('5262')); //false
複製代碼
//{n}能夠出現n個字符
let reg = /^\d{2}$/;
console.log(reg.test('')); //false
console.log(reg.test('2')); //false
console.log(reg.test('26')); //true
console.log(reg.test('2956')); //false
複製代碼
//{n,}能夠出現n到多個字符
let reg = /^\d{2,}$/;
console.log(reg.test('')); //false
console.log(reg.test('5')); //false
console.log(reg.test('861')); //true
複製代碼
//{n,m}能夠出現n次到m個字符
let reg = /^\d{2,4}$/;
console.log(reg.test('')); //false
console.log(reg.test('5')); //false
console.log(reg.test('52')); //true
console.log(reg.test('946')); //true
console.log(reg.test('9411')); //true
console.log(reg.test('55555')); //false
複製代碼
只要在正則中出現的元字符(在基於字面量方式建立),除了特殊和有量詞的之外,其他的都是普通元字符正則表達式
^$
和不加^$
的區別let reg = /\d+/; //=> 不加^和$,表明字符傳中只要包含xxx便可
console.log(reg.test('kl55ijs56k')); //true 包含0-9之間的任意數字
複製代碼
let reg1 = /^\d+$/; //=> 加^和$,表明字符傳中必須以0-9中的任意數字爲開頭和結尾
console.log(reg1.test('kl55ijs56k')); //false
console.log(reg1.test('5222')); //true
複製代碼
//方案一: 獲取'a b',去掉先後空格
let str = ' a b ';
//第一個for循環去掉了a前面的空格
for (var i = 0; i < str.length; i++) {
if (str[i] !== ' ') {
//若是循環到字符串中各項不是空格,就強制中止整個循環
break;
}
}
str = str.substring(i);//此時 str用var i爲全局變量
//第二個for循環去掉了b後面的空格
for (var k = str.length - 1; k > 0; k--) {
//從最後一位開始找,若是不是空格,就截取第一項到索引那項
if (str[k] !== ' ') {
str = str.substring(0, k + 1);
break;
}
}
console.log(str); //a b 去掉了先後空格
複製代碼
//方案二: 獲取'a b',去掉先後空格
let str = ' a b ';
str = str.trim(); //字符串方法:去掉字符串先後空格
console.log(str); //a b 去掉了先後空格
複製代碼
//方案三: 獲取'a b',去掉先後空格
let str = ' a b ';
let reg = /^\s+|\s+$/g; //以空格開頭或者以空格結尾
console.log(str.replace(reg, ''));
複製代碼
let reg = /^[.]+$/; //在這裏只是小數點
console.log(reg.test('n')); //false
console.log(reg.test('1')); //false
console.log(reg.test('\n')); //false
console.log(reg.test('nn')); //false
console.log(reg.test('.')); //true
複製代碼
但也有特殊狀況,例如:數組
let reg = /^[\d]+$/; //在這裏依然是表示0-9之間的任意數字
console.log(reg.test('2')); //true
console.log(reg.test('lks')); //false
複製代碼
let reg = /^[18]$/; //只能是1或者8
console.log(reg.test('1')); //true
console.log(reg.test('8')); //true
console.log(reg.test('18')); //false
let reg1 = /[18]/; //包含1或者8就能夠
console.log(reg1.test('1')); //true
console.log(reg1.test('8')); //true
console.log(reg1.test('18')); //true
console.log(reg1.test('958524')); //true
複製代碼
let reg = /^[13-56]$/; // 不是13~56 而是1或者3~5或者6
console.log(reg.test('1')); //true
console.log(reg.test('8')); //true
console.log(reg.test('6')); //false
複製代碼
// 一位數是正常的 從n到m
let reg = /^[2-5]$/;
console.log(reg.test('2')); //true
console.log(reg.test('8')); //false
console.log(reg.test('5')); //true
複製代碼
=======瀏覽器
18-19 1[89] 20-59 [2-5]\d 60-65 6[0-5]函數
let reg = /^( ( 1[89] ) | ( [2-5]\d ) | ( 6[0-5] ) ) $/;
console.log(reg.test('19'));
//trueoop
let reg = /^[object .+]$/; console.log(reg.test('[object AAA]')); //true學習
let str = '這個case很是international';
let num = 0;
for (let item of str) {
//[\u4e00-\u9fa5] 中文區間 若是字符串中的各項爲中文(即爲true)
if (/[\u4e00-\u9fa5]/.test(item)) {
num += 2;
}else{
num += 1;
};
};
複製代碼
//不加小括號的狀況
let reg = /^12|14$/; // 12或者14或者以12開頭或者以14結尾的均可以
console.log(reg.test('12')); //true
console.log(reg.test('14'));//true
console.log(reg.test('1214'));//true
console.log(reg.test('1258465414'));//true
console.log(reg.test('914'));//true
console.log(reg.test('123'));//true
console.log(reg.test('12ko'));//true
console.log(reg.test('+kj14'));//true
console.log(reg.test('12dsjjkn14'));//true
複製代碼
let reg = /^(12|14)$/; // 分組改變默認優先級
console.log(reg.test('12')); //true
console.log(reg.test('14'));//true
console.log(reg.test('1214'));//false
console.log(reg.test('1258465414'));//false
console.log(reg.test('914'));//false
console.log(reg.test('123'));//false
console.log(reg.test('12ko'));//false
console.log(reg.test('+kj14'));//false
console.log(reg.test('12dsjjkn14'));//false
複製代碼
let str = '2018---4//---/26//';
let reg = /(\d+)\D+(\d+)\D+(\d+)\D+/
let s = str.replace(reg,function($0,$1,$2,$3){
console.log($0); // 2018---4//---/26//
console.log($1); //2018
console.log($2); //4
console.log($3); //26
return `${$1}年${$2}月${$3}日`
});
console.log(s); //2018年4月26日
複製代碼
關於replace的兩個參數:請查看文末關於replace的內容ui
let reg = /^([a-z])([a-z])\2\1$/; //正則中出現的\1表明和第一個分組出現如出一轍的內容
console.log(reg.test('oppo')); //true
console.log(reg.test('poop')); //true
複製代碼
let str = '437826357384623537463363726573384633278467382';
let min = -Infinity; //定義一個負無窮大的數
str = str.split('').sort().join('');
// 把亂序字符串用空字符串分割成數組,排序數組,再轉成字符串,此時字符串爲 '222223333333333333444445556666666777777788888'
/* \d 1個數字 \d\1 2個同樣的數字 \d\1+ 2個到多個同樣的數字 /(\d)\1+/g 沒找到2個以上同樣的數字,函數就執行一次 */
str.replace(/(\d)\1+/g, function ($0, $1) {
// console.log($0); //22222 3333333333333 44444 555 6666666 7777777 88888
// console.log($1); // 2 3 4 5 6 7 8
if (min < $0.length) {
min = $0.length;
let index = $1
};
})
console.log(min, index); // 13 "3"
複製代碼
正則捕獲使用字符串的match
方法(正則exec方法不經常使用)this
?:
,表明當前分組只匹配不捕獲let str = '2019';
let reg = /(\d)+/;
console.log(str.match(reg));
// ["2019", "9", index: 0, input: "2019", groups: undefined]
// 不只把大正則的信息捕獲到,子項的信息也捕獲到
//注意:子項若是包了一個規則,在規則以後有量詞,那麼結果爲最後一個
複製代碼
+
-
號,能夠沒有,也能夠有一個0
12
9
:一位或者多位數字,一位0-9
,多位數字不能以0
開頭//利用正則檢測有效數字
let reg = /^[+-]?(\d|[1-9]\d)(\.\d+)?$/
複製代碼
let reg1 = /^1[3456789]\d{9}$/;
console.log(reg1.test('18704366271'));
複製代碼
[\u4E00-\u9FA5]
[\u4E00-\u9FA5]{2,}
//中文姓名 1)中文漢字[\u4E00-\u9FA5]{2,} 2)
let reg = /^[\u4E00-\u9FA5]{2,}((·)([\u4E00-\u9FA5]{2,}))?$/;
console.log(reg.test('湯姆')); //true
console.log(reg.test('湯姆·')); //false
console.log(reg.exec('湯姆·')); // null
console.log(reg.test('湯姆·漢克斯')); //true
console.log(reg.exec('湯姆·漢克斯'));
複製代碼
.
和 -
不能做爲開頭,不能連續出現 - 或者 .@
後面(域名):xxx.xx.xx
xxx.xx
xxx.xx.xx.xx
xxx-xxx-xx.xx.xx
let reg = /^\w+([-.]\w)*@[A-Za-z0-9]+([.-])[A-Za-z0-9]+)*(\.[A-Za-z0-9]+)$/
複製代碼
let reg2 = /^\d{6}((18\d\d)|(19\d\d)|(20[01]\d))(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}[\dxX]$/;
console.log(reg2.test('220802199603241523'));
複製代碼
test()
exec()
test()
match
split
replace
基於exec
能夠實現正則捕獲
null
0
:大正則捕獲的內容index
:正則捕獲的起始索引input
:原始操做的字符串exec
只能捕獲到第一個和正則匹配的內容,其他匹配的內容尚未捕獲到,並且執行屢次也無效 => 正則捕獲的懶惰性正則捕獲的懶惰性:只能捕獲到第一個匹配的內容,剩餘的默認捕獲不到
let str = 'hello2018hello2019';
let str1 = 'hellohello';
let reg = /\d+/;
console.log(reg.test(str)); //true
console.log(reg.test(str1)); //false
console.log(reg.exec(str1)); // null
console.log(reg.exec(str)); //["2018", index: 5, input: "hello2018hello2019", groups: undefined]
複製代碼
lastIndex
不變lastIndex
正則捕獲時候,下一次在字符串中開始查找的索引let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/;
console.log(reg.exec(str)); //=> 2018
console.log(reg.lastIndex); //=> 0
console.log(reg.exec(str)); //=> 2018
console.log(reg.lastIndex); //=>0
// 即便手動修改了lastIndex值 依舊無效
reg.lastIndex = 11;
console.log(reg.lastIndex); //=>0
複製代碼
// 解決正則懶惰性:加全局修飾符g
let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/g;
console.log(reg.lastIndex); //=> 0
console.log(reg.exec(str)); //=> 2018
console.log(reg.lastIndex); //=> 11
console.log(reg.exec(str)); //=> 2019
console.log(reg.lastIndex); //=>22
console.log(reg.exec(str)); //=> null
console.log(reg.lastIndex); //=>0
console.log(reg.exec(str)); //=> 2018
複製代碼
let str = 'zhufeng2018zhufeng2019yangfan2020qihang2021';
let reg = /\d+/g;
RegExp.prototype.myExecAll = function(str){
// 爲了防止出現死循環,咱們檢測一下正則是否加g,沒有加g只把第一次捕獲的結果返回便可
if(!this.global){
return this.exec(str);
};
//this:reg 當前操做的正則
//執行exec開始捕獲,具體捕獲多少次不定,可是一直到捕獲不到內容(null)爲止,期間把捕獲到的內容存儲到數組中
let result = [];
let valAry = this.exec(str);
while(valAry){ //=>this.lastIndex < str.length
result.push(valAry[0]); //=>把每次捕獲到的結果第一項(具體捕獲的內容)存儲到容器中
valAry = this.exec(str);
};
return result;
};
console.log(reg.myExecAll(str));
//["2018", "2019", "2020", "2021"]
複製代碼
let str = 'zhufeng2018zhufeng2019yangfan2020qihang2021';
let reg = /\d+/g;
console.log(str.match(reg));
//["2018", "2019", "2020", "2021"]
複製代碼
字符串方法:match
實現了本身編寫的execAll處理的事情,但也要加全局修飾符g,把全部匹配的內容都捕獲到,最後統一存儲到一個數組中返回
match()
方法可在字符串內檢索指定的值,或找到一個或多個正則表達式的匹配。
match
實現了本身編寫的execAll
處理的事情,但也要加全局修飾符g
,把全部匹配的內容都捕獲到,最後統一存儲到一個數組中返回
let str = 'zhufeng{2018}zhufeng{2019yangfan{2020}qihang{2021}';
let reg = /\{(?:\d+)\}/g; //大括號有特殊含義:{n}出現的次數
console.log(reg.exec(str));
//["{2018}", "2018", ...]
console.log(str.match(reg)); //=>{2018}", "{2019}", "{2020}", "{2021}
複製代碼
/\{(?:\d+)\}/g
=> ?:
是用來阻止分組捕獲內容的 「只匹配不捕獲」console.log(str.match(reg));
//=>{2018}", "{2019}", "{2020}", "{2021}
match方法也有本身的侷限性,在正則設置了g
,基於match
捕獲的內容只有大正則匹配的,小分組的內容沒有單獨抽取出來
每一次匹配捕獲的時候,老是捕獲到和正則匹配中最長的內容,例如:2
符合 \d+
2018
也符合 \d+
,可是捕獲的是最長的內容 2018
let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/g;
console.log(reg.exec(str)); //["2018", ...]
複製代碼
解決方案:在量詞元字符後面加?
, 表明的不是出現0-1次,而是取消正則捕獲貪婪性
let str = 'zhufeng2018zhufeng2019';
let reg1 = /\d+?/g;
console.log(reg1.exec(str)); // ["2", ...]
複製代碼
?
在正則中的做用/-?/
讓減號出現或者不出現/\d+?/
只捕獲最短匹配內容?:
只匹配不捕獲?=
正向預查?!
負向預查test()
和exec()
test
進行匹配的時候,若是設置了g
,test
匹配也至關於捕獲,修改了lastIndex
的值let str = 'zhufeng2018zhufeng2019';
let reg = /\d+/g;
console.log(reg.test(str)); //true
console.log(reg.lastIndex); //11
console.log(reg.exec(str));//["2019",...]
複製代碼
let str = 'zhufeng2018';
let reg = /\d+/g;
console.log(reg.exec(str));//[2018] 把reg.lastIndex值修改了
console.log(reg.exec('zhufeng2018zhufeng2019')); //[2019] 雖然捕獲的不是同一個字符串,可是正則是同一個,上一次正則處理的時候修改了它的lastIndex,也會對下一次匹配的字符串產生影響
複製代碼
RegExp.$1
把上一次匹配(test/exec)到的結果獲取到,獲取的是第一個小分組匹配的內容,大正則匹配的內容沒法獲取,他是一個全局的值,瀏覽器中$1只有一個,其餘的正則操做也會覆蓋這個值,因此這種方式通常不用let str = 'zhufeng2018peixun2019';
let reg = /(\d+)/g;
console.log(reg.test(str)); //true
console.log(RegExp.$1); //2018
console.log(reg.test(str)); //true
console.log(RegExp.$1); //2019
console.log(reg.test(str));//false
console.log(RegExp.$1); //2019
console.log(reg.test(str));//true
console.log(RegExp.$1); //2018
複製代碼
replace:實現正則捕獲的方法(自己是字符串替換)
// 需求:把全部的'zhufeng'替換成'zhufengpeixun'
let str = 'zhufeng2018zhufeng2019';
let reg = /(\d+)/g;
str = str.replace('zhufeng','zhufengpeixun'); //一次只能替換一個,第二次仍是從索引[0]開始替換
複製代碼
let str = 'zhufeng2018zhufeng2019';
str = str.replace(/zhufeng/g,'zhufengpeixun');
console.log(str); //zhufengpeixun2018zhufengpeixun2019
複製代碼
//不經常使用
let str = 'zhufeng{val:2018}zhufeng{val:2019}';
reg = /\{val:(\d+)\}/g;
str = str.replace(reg,'#'); // 用reg正則和str字符進行匹配,匹配幾回就替換幾回,每一次都是當前「大正則」匹配的結果用第二個傳遞的字符串替換掉了
console.log(str); //zhufeng#zhufeng#
複製代碼
//不常見
let str = 'zhufeng{val:2018}zhufeng{val:2019}';
reg = /\{val:(\d+)\}/g;
str = str.replace(reg,'$1'); // $1不是拿這個字符替換掉大正則匹配的內容,此處的$1表明第一個分組匹配的內容,等價於 RegExp.$1
console.log(str); //zhufeng2018zhufeng2019
複製代碼
原理:string.replace(要替換的字符串||正則,替換成什麼||函數);
//經常使用
let str = 'zhufeng{val:2018}zhufeng{val:2019}';
reg = /\{val:(\d+)\}/g;
str = str.replace(reg,(...arg) =>{
console.log(arg);
return 'AA';
});
console.log(str);//zhufengAAzhufengAA
複製代碼
當第二個參數爲函數的時候(默認狀況下)
2.若是有小括號提權,則:
此函數必需要有return,否則默認爲undefined
多個小括號嵌套的狀況: /((\d+)\D+(\d+))\D+(\d+)\D+/
let str = '2018---4//---/26//';
let reg = /(\d+)\D+(\d+)\D+(\d+)\D+/
let s = str.replace(reg,function($0,$1,$2,$3){
console.log($0); // 2018---4//---/26//
console.log($1); //2018
console.log($2); //4
console.log($3); //26
return `${$1}年${$2}月${$3}日`
});
console.log(s); //2018年4月26日
複製代碼
let str = '爲人民服務,爲人民奮鬥,爲人民努力'
let s = str.replace(/服務|奮鬥|努力/g,function($0,$1){
let temp = '';
for (let i = 0; i < $0.length; i++) {
temp += '*';
};
console.log($0); //服務 奮鬥 努力
return temp
})
console.log(s); // 爲人民**,爲人民**,爲人民**
複製代碼