regular expression :
RegExp
/ˈreɡjələr/ /ɪk'sprɛʃən/ 用來處理字符串的規則javascript
- 只能處理字符串
- 它是一個規則:能夠驗證字符串是否符合某個規則,也能夠把字符串中符合規則的內容捕獲到(test/exec/match...);
let str = 'good good study,day day up!';
=> 學正則就是用來制定規則;
let reg = /\d+/;
reg.test(str); =>false;
str = '2019-08-12';
reg.exec(str); =>["2019", index: 0, input: "2019-08-12", groups: undefined]
複製代碼
建立方式有兩種:java
=> 一、字面量建立方式 兩個斜杆之間包起來的,都是用來描述規則的元字符;
let reg1 = /\d+/ ;
正則表達式=>二、構造函數模式建立
兩個參數:元字符字符串,修飾符字符串;let reg2 = new RegExp('\\d+');
算法
- * 表示0次或者屢次,等同於{0,},即c* 和c{0,} 是一個意思。
- + 表示一次或者屢次,等同於{1,},即c+ 和c{1,} 是一個意思。 最後;
- ? 表示0次或者1次,等同於{0,1},即c? 和c{0,1} 是一個意思。;
- {n} 出現n次;
- {n,} 出現n 到屢次
- {n,m} 出現n到m次數;
- \ 轉譯字符(普通->特殊->普通)
- . 除\n (換行符)之外的任意字符;
- ^ 以哪個元字符做爲開始;
- $ 以哪個元字符做爲結束;
- \n 換行符;
- \d 0~9之間的一個數字;
- \D 匹配一個非數字字符。等價於 ^0-9;
- \w 數字、字母、下劃線中任意一個字符;
- \s 一個空白字符(包含空格、製表符、換頁符等)
- \t 一個製表符(一個TAB鍵:四個空格);
- \b 邊界符; 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 能夠匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
- x|y x或者y中的一個字符;
- [xyz] x或者y或者z中的一個字符;
- [^xy] 除了x、y之外的任意字符;
- [a-z]指定a-z這個範圍中的任意字符 [0-9a-zA-Z_]=== \w
- [^a-z] 上一個的取反「非」;
- () 正則中的分組符號;
- (?:) 只匹配不捕獲
- (?=) 正向預查
- (?!) 負向預查
i => ignoreCare 忽略單詞大小寫匹配;express
m =>multiline 能夠進行多行匹配;數組
g => global 全局匹配bash
/A/.test('lalala')
=>falseide
/A/i.test('lalala')
=>true函數
^
$
ui
^/$
兩個都不加:字符串中包含符合規則的內容便可;let str = '146576567djkljkljl6787897'`
let reg1 = /\d+/;`只要有數字就能夠了)
reg1.test(str) // true
複製代碼
^/$
兩個都加:字符串只能是和規則一致的內容;let reg2 = /^\d+$/;(從頭至尾必須所有都是數字)
reg2.test(str) // false
複製代碼
例子:驗證手機號碼(11位,第一個數字是1既可);
let reg = /^1\d{10}$/;
let reg = /^\d/;
reg.test('world'); =>false
reg.test('2019world'); =>ture
reg.test('world2019'); =>false
let reg = /\d$/;
reg.test('world'); =>false
reg.test('2019world'); =>false
reg.test('world2019'); =>ture
複製代碼
\
.
不是小數點,是除\n外的任意字符
let reg = /^2.3$/;
console.log(reg.test("2.3"));//=>true
console.log(reg.test("2@3"));//=>true
console.log(reg.test("23"));//=>false
//=>基於轉義字符,讓其只能表明小數點
reg = /^2\.3$/;
console.log(reg.test("2.3"));//=>true
console.log(reg.test("2@3"));//=>false
let str = "\\d";
reg = /^\d$/; //=>\d表明0-9的數字
console.log(reg.test(str)); //=>false
reg = /^\\d$/; //=>把特殊符合轉換爲普通的(\把\d中的\轉移成\自己=> 只能是 \d)
console.log(reg.test(str)); //=>true
複製代碼
x|y
let reg = /^18|29$/; // => 以1開頭 9 結尾 =>中間是8或者2 // 以18開頭 29結尾均可以,條件不少
console.log(reg.test("18")); //=>true
console.log(reg.test("29")); //=>true
console.log(reg.test("129")); //=>true
console.log(reg.test("189")); //=>true
console.log(reg.test("1829")); //=>true
console.log(reg.test("829")); //=>true
console.log(reg.test("182")); //=>true
//---直接x|y會存在很亂的優先級問題,通常咱們寫的時候都伴隨着小括號進行分組,由於小括號改變處理的優先級 =>小括號:分組
reg = /^(18|29)$/;
console.log(reg.test("18")); //=>true
console.log(reg.test("29")); //=>true
console.log(reg.test("129")); //=>false
console.log(reg.test("189")); //=>false
//=>只能是18或者29中的一個了
複製代碼
[]
//1.中括號中出現的字符通常都表明自己的含義;
let reg = /^[@+]$/; // 出現@ 或者 +其中一個
console.log(reg.test("@")); //=>true
console.log(reg.test("+")); //=>true
console.log(reg.test("@@")); //=>false
console.log(reg.test("@+")); //=>false
//=>\d在中括號中仍是0-9
reg = /^[\d]$/;
console.log(reg.test("d"));//=>false
console.log(reg.test("\\"));//=>false
console.log(reg.test("9"));//=>true
//2.中括號中不存在多位數
reg = /^[18]$/;
console.log(reg.test("1")); //=>true
console.log(reg.test("8")); //=>true
console.log(reg.test("18")); //=>false
reg = /^[10-29]$/; //=>1或者0-2或者9
console.log(reg.test("1"));//=>true
console.log(reg.test("9"));//=>true
console.log(reg.test("0"));//=>true
console.log(reg.test("2"));//=>true
console.log(reg.test("10"));//=>false
複製代碼
/* * 規則分析 * 1.可能出現 + - 號,也可能不出現 [+-]? * 2.一位0-9均可以,多位首位不能是0 (\d|([1-9]\d+)) * 3.小數部分可能有可能沒有,一旦有後面必須有小數點+數字 (\.\d+)? */
let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/;·
複製代碼
//=>數字、字母、下劃線
//=>6~16位
let val = userPassInp.value,
reg = /^\w{6,16}$/;
let flag=reg.test(val);
/*
function checkPass(val){
if(val.length<6 || val.length>16){
alert('長度必須介於6-16位之間!');
return;
}
let area=['a','b'....'_']; //=>包含數字、字母、下劃線
for(let i=0;i<val.length;i++){
let char=val[i];
if(!area.includes(char)){
alert('格式不正確!');
return;
}
}
}
*/
複製代碼
* 1.漢字 /^[\u4E00-\u9FA5]$/
* 2.名字長度 2~10位
* 3.可能有譯名 ·漢字 (·[\u4E00-\u9FA5]{2,10}){0,2}
*/
let reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10}){0,2}$/;
複製代碼
let reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
//=> \w+((-\w+)|(\.\w+))*
1.開頭是數字字母下劃線(1到多位)
2.還能夠是 - 數字字母下劃線 或者 .數字字母下劃線,總體零到屢次
//=>郵箱的名字由「數字、字母、下劃線、-、.」幾部分組成,可是-/.不能連續出現也不能做爲開始;
/^\w+/
//=> @[A-Za-z0-9]+
//1.@後面緊跟着:數字、字母 (1-多位)
//=> ((\.|-)[A-Za-z0-9]+)*
//1.對@後面名字的補充
// 多域名 .com.cn
// 企業郵箱 zxt@zhufeng-peixun-office.com
//=> \.[A-Za-z0-9]+
//1. 這個匹配的是最後的域名(.com/.cn/.org/.edu/.net...)
複製代碼
/*
* 1. 一共18位
* 2. 最後一位多是X
*
* 身份證前六位:省市縣 130828
* 中間八位:年月日
* 最後四位:
* 最後一位 => X或者數字
* 倒數第二位 => 偶數 女 奇數 男
* 其他的是通過算法算出來的
*/
//let reg = /^\d{17}(\d|X)$/;
//=>小括號分組的第二個做用:分組捕獲,不只能夠把大正則匹配的信息捕獲到,還能夠單獨捕獲到每一個小分組的內容
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;
reg.exec("130828199012040617"); //=>["130828199012040617", "130828", "1990", "12", "04", "1", "7"...] 捕獲結果是數組,包含每個小分組單獨獲取的內容
複製代碼
構造函數由於傳遞的是字符串,\
須要寫兩個才表明斜槓 let reg = /\d+/g;
reg = new RegExp("\\d+","g");
正則表達是中的部份內容是變量存儲的值
1.兩個斜槓中間包起來的都是元字符(若是正則中要包含某個變量的值,則不能使用字面量方式建立)
let type = "hahahaha";
reg = /^@"+type+"@$/; // 以@ 開始/結束," 出現屢次 typ e出現屢次」
console.log(reg.test("@hahaha@")); //=>false
console.log(reg.test('@"""typeeeee"@')); //=>true
//2.這種狀況只能使用構造函數方式(由於它傳遞的規則是字符串,只有這樣才能進行字符串拼接)
reg = new RegExp("^@"+type+"@$"); // type 爲變量;
console.log(reg.test("@hahahaha@"));//=>true
複製代碼
實現正則捕獲的辦法
let str = "lyridel2019yangfan2020qihang2021";
let reg = /\d+/;
複製代碼
- 基於exec實現正則的捕獲
- 1.捕獲到的結果是null或者一個數組
- 第一項:本次捕獲到的內容
- 其他項:對應小分組本次單獨捕獲的內容
- index:當前捕獲內容在字符串中的起始索引
- input:原始字符串
- 2.每執行一次exec,只能捕獲到一個符合正則規則的,可是默認狀況下,咱們執行一百遍,獲取的結果永遠都是第一個匹配到的,其他的捕獲不到
=>「正則捕獲的懶惰性」:默認只捕獲第一個捕獲的內容
let str = "ddhwe2019yangfan2020qihang2021";
- reg.lastIndex:當前正則下一次匹配的起始索引位置
- 懶惰性捕獲的緣由:默認狀況下lastIndex的值不會被修改,每一次都是從字符串開始位置查找,因此找到的永遠只是第一個
let reg = /\d+/;
console.log(reg.lastIndex); //=>0 下面匹配捕獲是從STR索引零的位置開始找
console.log(reg.exec(str));
console.log(reg.lastIndex); //=>0 第一次匹配捕獲完成`
lastIndex沒有改變,因此下一次exec依然是從字符串最開始找,找到的永遠是第一個匹配到的
複製代碼
解決辦法:全局修飾符g
可是需注意:匹配最後一次,沒有以後會返回null,再匹配lastIndex爲0 開始尋找
let reg = /\d+/g;
console.log(reg.exec(str)); //=>["2019"...]
console.log(reg.lastIndex); //=>11 設置全局匹配修飾符g後,第一次匹配完,lastIndex會本身修改
console.log(reg.exec(str)); //=>["2020"...]
console.log(reg.lastIndex); //=>22
console.log(reg.exec(str)); //=>["2021"...]
console.log(reg.lastIndex); //=>32
console.log(reg.exec(str)); //=>null 當所有捕獲後,再次捕獲的結果是null,可是lastIndex又迴歸了初始值零,再次捕獲又從第一個開始了...
console.log(reg.lastIndex); //=>0
console.log(reg.exec(str)); //=>["2019"...]
複製代碼
每一次捕獲都按照正則匹配的最長結果捕獲
let str = 'jkldjkl1234';
let reg = /\d+/g;
+ 表明1-多位,可是正則匹配只按照最長的匹配
複製代碼
需求:編寫一個方法execAll,執行一次能夠把全部匹配的結果捕獲到(前提正則必定要設置全局修飾符g)
~ function () {
function execAll(str = "") {
//=>str:要匹配的字符串
//=>this:RegExp的實例(當前操做的正則)
//=>進來後的第一件事,是驗證當前正則是否設置了G,不設置則不能在進行循環捕獲了,不然會致使死循環
if (!this.global) return this.exec(str);
//=>ARY存儲最後全部捕獲的信息 RES存儲每一次捕獲的內容(數組)
let ary = [],
res = this.exec(str);
while (res) {
//=>把每一次捕獲的內容RES[0]存放到數組中
ary.push(res[0]);
//=>只要捕獲的內容不爲NULL,則繼續捕獲下去
res = this.exec(str);
}
return ary.length === 0 ? null : ary;
}
RegExp.prototype.execAll = execAll;
}();
let reg = /\d+/g;
console.log(reg.execAll("DD2019@2020不少3GD")); //=> ["2019", "2020", "3"]
複製代碼
//=>字符串中的MATCH方法,能夠在執行一次的狀況下,捕獲到全部匹配的數據(前提:正則也得設置G才能夠)
//=>身份證號碼
let str = "130828199012040112";
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(?:\d|X)$/;
console.log(reg.exec(str));
console.log(str.match(reg));
//=>["130828199012040112", "130828", "1990", "12", "04", "1", index: 0, input: "130828199012040112"]
//=>第一項:大正則匹配的結果
//=>其他項:每個小分組單獨匹配捕獲的結果
//=>若是設置了分組(改變優先級),可是捕獲的時候不須要單獨捕獲,能夠基於?:來處理
複製代碼
//=>既要捕獲到{數字},也想單獨的把數字也獲取到,例如:第一次找到 {0} 還須要單獨獲取0
let str = "{0}年{1}月{2}日";
/* //=>不設置g只匹配一次,exec和match獲取的結果一致(既有大正則匹配的信息,也有小分組匹配的信息) let reg = /\{(\d+)\}/; console.log(reg.exec(str)); console.log(str.match(reg)); //["{0}", "0",...] */
let reg = /\{(\d+)\}/g;
//console.log(str.match(reg)); //=>["{0}", "{1}", "{2}"] 屢次匹配的狀況下,match只能把大正則匹配的內容獲取到,小分組匹配的信息沒法獲取
let aryBig=[],
arySmall=[],
res=reg.exec(str);
while(res){
let [big,small]=res;
aryBig.push(big);
arySmall.push(small);
res=reg.exec(str);
}
console.log(aryBig,arySmall); //=>["{0}", "{1}", "{2}"] ["0", "1", "2"]
複製代碼