js正則限制字符串長度_正則筆記(3)萬字長文,慎點。

68de7a671e9e63f40f18a7c9f8df9ac0.gif

正則講了很久,也拖了很久,今天看看怎么用吧,后續更文應該會比較準勤快了。:-)

書接上文【正則筆記(2)】。這次我們來看看正則的使用:

(注:斜體表示為對應規則寫出的正則表達式)

一、 常用的正則表達式:

1. 驗證是否為有效數字:
規則分析:
a. 可能出現 + - 號,也可能不出現。那么根據該規則我們可以寫出正則:[+-]?
b.如果是1位數字那么0-9都可以,如果是多位數字,則首位不能為0。則我們可以寫出正則:\d|([1-9]\d+)
c.小數部分可能有也可能沒有。一旦有小數部分則必須有小數點+數字 。對應正則:(\.\d+)?


綜合以上的幾個部分,所以我們知道驗證有效數字的正則可以寫成:

let?reg?=?/^[+-]?(\d|([1-9]\d+))(\.\d+)?$/;

通過上面的分析,發現了嗎?寫正則表達式一般我們是按位來寫。

2.驗證密碼的正則:

規則分析:
a. 數字,字母,下劃線
b. 6-16位

為了讓各位看客體驗一下正則的強大,我們先用傳統JS的方法來校驗一下密碼:

//不用正則:let?val?=?userPassInp.value;?//這里表示從密碼框中獲取密碼值function?checkPass(val)?{  if (val.length<6 || val.length>16) {    alert('長度必須介于6-16位之間');    return;  }??let?area?=?['a','/**...這里表示的是a-z,A-Z,0-9,_*/'];?//?這里應該是包含字母數字下劃線的數組  for(let i=0; i<val.length; i++) {    let char = val[i];    if (!area.includes(char)) {      alert('密碼格式不正確');      return;    }  }}

是不是有點冗長?那么來看一下正則校驗密碼:

let reg2 = /^\w{6-16}$/;let?flag?=?reg2.test(val);?//?若 flag?為true則表示正確

簡單多了吧,有沒有分分鐘愛上正則?

3.驗證真實姓名:

規則:
a.漢字。那么應該對應中文第一個漢字到最后一個漢字的Unicode編碼值,即:/^[\u4E00-\u9FA5]$/

b. 名字長度2-10位。即:{2,10}

c.可能有譯名的情況發生,比如:'尼古拉·趙四',·后面暫定1-10位吧,可以酌情修改。(·[\u4E00-\u9FA5]{1,10})?

let?reg?=?/^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{1,10})?$/;reg.test('孫尚香');?//?truereg.test('cos'); // false 必須是中文reg.test('尼古拉·趙四'); // true

4.驗證郵箱:
規則:
a.開頭必須是字母、數字、下劃線 (可以1-多次)。即:? \w+

比如:

????sun-shang-xiang????sun.shang.xiang

????sun-shang.xiang

b.還可以是 -字母數字下劃線 或者 .數字字母下劃線, 整體0到多位。即: ((-\w+)|(\.\w+))*(注:郵箱的名字由數字、字母、下劃線、中劃線、點、幾部分組成,但是 中劃線和點不能連續出現,也不能作為開始)
c. @符后面緊跟著:數字,字母(可以是一直多位)。即: [A-Za-z0-9]+

d. 我們還需要對@符號后面的內容做一些補充,因為:

①有可能是多域名郵箱比如:.com.cn
②也可能企業域名 ssx@shuhan-wangchao-office.com? //孫尚香@蜀漢-王朝-辦公室.com

所以:((\.|-)[A-Za-z0-9]+)*

e-? 匹配最后的域名,比如:(.com .cn .org .net .edu)。即:\.[A-Za-z0-9]+

綜上,郵箱的正則為:

let?reg?=?/^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;

5.身份證號碼:

規則:

a.一共18位
b.?最后以為可能是X
c. 身份證前六位是省市縣
d. 中間8位是出生年月日
e. 最后四位:
????最后1位是X或者數字 ?
????倒數第二位偶爾是女 奇數是男
????其余的是經過算法算出來

let?reg?=?/^\d{17}(\d|X)$/;

我們來分析一下上面這一段正則:
在這里我們遇到了 () 的第二個作用:分組捕獲。

不僅可以把大正則匹配的信息捕獲到,還可以單獨捕獲到每個小分組的內容

比如:

let?reg?=?/^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;reg.exec('410521199303088019');?//?正則捕獲??捕獲的結果是個數組?包含了每個小分組單獨獲取的內容

我們來看一下分組捕獲到的具體內容:
0: "410521199303088019"
1: "410521"
2: "1993"
3: "03"
4: "08"
5: "1"
6: "9"
groups: undefined
index: 0
input: "410521199303088019"
length: 7

二、兩種創建正則的方式之間的區別:

1- 字面量創建:

let reg = /\\/;reg.test('\\');?//true//或者這樣:let?reg2?=?/\d+/g;

2- 構造函數模式創建: 這種寫法RegExp有2個參數:元字符字符串 和 修飾符字符串

let?reg?=?new?RegExp('\\d+','g');// ==>構造函數因為傳遞的是字符串,\需要些兩個才代表斜杠。

說明:

1.正則表達式中的部分內容是變量存儲的值
2.兩個斜杠包起來的部分都是元字符 (如果正則中要包含某個變量的值,則不能使用字面量方式創建)
3.如果正則中包含某個變量只能使用構造函數的形式 (因為它傳遞的是字符串,只有這樣才能進行字符串拼接)

舉個栗子叭。

字面量形式:

let?type?=?'cos';let?reg?=?/^@"+type+"@$/;reg.test("@cos@");?//==>?falsereg.test('@"""typeeeee"@');?//==>?true?因為正則中的?+?號被作為元字符了

構造函數形式:

let?reg?=?new?RegExp('^@'+?type?+'@$');reg5.test("@cos@");?// true

三、正則捕獲:
1- 實現正則捕獲的方法:
正則RegExp.prototype上的方法
??????? exec
??????? test

937f7cf0e284cdf45394fb39f61a80ff.png

2- 字符串String.prototype上支持正則表達式處理的方法:
????? replace
????? match
????? splite
????? ...

常用正則表達式的方法:

exec:一個在字符串中執行查找匹配的RegExp方法,它返回一個數組(未匹配到則返回 null)。test:一個在字符串中測試是否匹配的RegExp方法,它返回 true 或 false。match:一個在字符串中執行查找匹配的String方法,它返回一個數組,在未匹配到時會返回 null。matchAll:一個在字符串中執行查找所有匹配的String方法,它返回一個迭代器(iterator)。search:一個在字符串中測試匹配的String方法,它返回匹配到的位置索引,或者在失敗時返回-1。replace:一個在字符串中執行查找匹配的String方法,并且使用替換字符串替換掉匹配到的子字符串。split:一個使用正則表達式或者一個固定字符串分隔一個字符串,并將分隔后的子字符串存儲到數組中的 String 方法。

3-正則捕獲的懶惰性:

如果我們想捕獲字符串str中所有的數字:

let str = "cos2019yangfan2020qihang2021";// 捕獲str中所有的數字 (首先正則得匹配才行)// 實現正則捕獲的前提是 當前正則要和對應字符串匹配,如果不匹配捕獲的結果為nulllet reg = /^\d+/;reg.test(str); //==> falsereg.exec(str);?//==>?null 沒有匹配到所以返回nulllet reg2 = /\d+/;reg2.test(str);?//==>?falsereg2.exec(str);?//==>?得到的結果是個數組?["2019",?index:?3,?input:?"cos2019yangfan2020qihang2021",?groups:?undefined]

基于exec實現正則的捕獲:
1-捕獲到的結果是null或者一個數組 。
數組第一項:為本次捕獲到的內容? ?
其余項是對應小分組單獨捕獲的內容
index: 當前捕獲的結果在字符串中的起始位置
input: 原始字符串
2-每執行一次exec方法只能捕獲到一個符合正則規則的,但是默認情況下,我們執行多次,獲取的結果永遠都是第一個匹配到的,其余的捕獲不到,這個叫做正則捕獲的懶惰性

正則捕獲懶惰性的原理:

這一切都要從RegExpObject.lastIndex 說起,lastIndex 屬性用于規定下次匹配的起始位置。

正則捕獲懶惰性的原因是:默認情況下 lastIndex 的值不會被修改,
每一次都是從字符串開始位置查找,
所以找到的永遠是第一個
解決辦法:使用全局修飾符? g

// exec原理:letstr = "cos2019yangfan2020qihang2021";letreg = /\d+/;reg.lastIndex;?//==>?0?下面匹配捕獲是從str索引為0的位置開始找reg.exec(str);?//==>?['2019',...]reg.lastIndex;?//==>?0?注意:lastIndex沒有改變

第一次匹配捕獲完成,lastIndex沒有改變,所以下一次exec依然是從字符串最開始找,找到的永遠是第一個匹配到的,所有的捕獲方法都遵循這個規則(因為是正則本身的機制)。

正則捕獲懶惰型的解決方案:修飾符 g

let str = "cos2019yangfan2020qihang2021";let reg = /\d+/g;reg.lastIndex;?//==>?0reg.exec(str);?//==>?['2019'...]reg.lastIndex;?//==>?7// 注意:設置全局匹配修飾符g后,第一次匹配完,lastIndex的值會自己修改reg.exec(str);?//==>?['2020'...]reg.lastIndex;?//==>?18reg.exec(str);?//==>?['2021'...]reg.lastIndex;?//==>?28reg.exec(str);?//==>?null?當全部捕獲后,再次捕獲的結果是null,但是lastIndex又回到了初始值0,再次捕獲,又從第一個開始了...reg.lastIndex;?//==>?0reg.exec(str);?//==>?['2019'...]

仔細看會發現,當exec匹配到null之后,又從字符串開端重新開始匹配了。這是因為,當全部捕獲后,再次捕獲的結果是null,但是lastIndex又回到了初始值0,再次捕獲,又從第一個開始了...

重要事項:不具有標志 g 和不表示全局模式的 RegExp 對象不能使用 lastIndex 屬性。

因為我們說只有正則能夠在字符串中匹配到值的情況下,捕獲才有意義,所以可能可能有人會這么想:是不是可以先使用test()方法來檢測一下正則能否匹配到字符串中的值,如果能匹配到值,再進行捕獲。

但是這種方案是不對的:

//?如果字符串不符合正則,那么就無法捕獲// 下面的解決方案是有問題的:let str = "cos2019yangfan2020qihang2021";let reg = /\d+/g;if?(reg.test(str))?{????//?驗證一下:?只有正則和字符串匹配我們再捕獲???console.log(reg.lastIndex);?//?7?基于test匹配驗證后,   console.log(reg.exec(str)); // ==>  ['2020',...]  lastIndex已經被修改為第一次匹配后的結果,所以下一次捕獲不再從頭開始了}

存在的問題: 如果這么寫那么我們就沒有辦法匹配到第一個符合規則的值了。

于是,我們提出一個需求:編寫一個方法execAll,執行一次可以把所有匹配的結果捕獲到(前提,正則一定要設置全局修飾符g)

~function() {  function execAll(str = '') {????//?進來后的第一件事,就是驗證當前正則是否設置了g,????//?不設置則不能再進行循環捕獲了,否則會導致死循環    if(!this.global) return this.exec(str);        // => str:要匹配的字符串        // => this:RegExp的示例(當前操作的正則)                // ary存儲最后所有捕獲的信息  reg存儲每一次捕獲的內容        let ary = [];        let res = this.exec(str);        while(res) {??????????ary.push(res[0]);???????????//?把每一次捕獲的內容存放到數組當中          // => 只要捕獲的內容不為null,則繼續捕獲下去          res = this.exec(str);????????}        return ary.length === 0 ? null : ary;      }      RegExp.prototype.execAll = execAll;}();

使用:

// 加g:let str = "cos2019yangfan2020qihang2021";let reg = /\d+/g;reg.execAll(str);?//?['2019,'2020','2021']let str2 = 'hhh';let str3 = '12@13hhh'reg.execAll(str2);?//?nullreg.execAll(str3);?//?['12,'13']
// 不加g的情況下:let reg2 = /\d+/;reg2.execAll(str2);?//?nullreg2.execAll(str3);?//?["12",?index:?0,?input:?"12@13hhh",?groups:?undefined]

其實還有一種辦法,就是直接使用字符串的match方法:

str3.match(reg2);  // ["12", "13"]// 字符串中的match方法,可以在執行一次的情況下,捕獲到所有匹配的數據(前提是正則必須加g才可以)

4-正則的分組捕獲:

身份證號碼:

let?str?=?'610521199003020017';let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(?:\d|X)$/;reg.test(str);?//?truereg.exec(str);?//?["610521199003020017",?"610521",?"1990",?"03",?"02",?"1",?"7",?index:?0,?input:?"610521199003020017",?groups:?undefined]str.match(reg);//?["610521199003020017",?"610521",?"1990",?"03",?"02",?"1",?"7",?index:?0,?input:?"610521199003020017",?groups:?undefined]

我們對上述正則不活的內容做一個分析:

????a.數組第一項是大正則匹配的結果
??? b.其余項:每一個小分組單獨匹配捕獲的結果
????c.如果設置了分組(改變優先級)但是捕獲的時候不需要單獨捕獲,可以基于?:(只匹配不捕獲)來處理
????d.比如我不想要最后一項(因為沒有用),我們不能去掉小括號,因為|會存在優先級的問題,所以我在最后一項的括號中添加一個 ?: 表示只匹配不捕獲(?:\d|X) 這個時候就不會捕獲到最后的一項了

5-分組捕獲

比如我們定義了一個字符串時間格式為:{2019}年{11}月{8}日

既要捕獲到{數字},也想單獨的把數字也獲取到,例如:第一次找到{0},還需要單獨獲取0

let str = "{2019}年{11}月{8}日";let reg = /\{\d+\}/;   reg.exec(str);?//["{2019}",?index:?0,?input:?"{2019}年{11}月{8}日",?groups:?undefined]str.match(reg);?//["{2019}",?index:?0,?input:?"{2019}年{11}月{8}日",?groups:?undefined]

這種情況下只能捕獲到大正則不能捕獲小分組。????

那如何才能獲取到小分組呢:

 // 加小括號,分組捕獲:let str = "{2019}年{11}月{8}日";let reg = /\{(\d+)\}/;reg.exec(str);?//?["{2019}",?"2019",?index:?0,?input:?"{2019}年{11}月{8}日",?groups:?undefined]str.match(reg);?//?["{2019}",?"2019",?index:?0,?input:?"{2019}年{11}月{8}日",?groups:?undefined]

分組捕獲,先匹配大正則,再把對應的小分組匹配到。

但問題又來了,如果我想多次匹配呢?

// 加小括號,加g:let str = "{2019}年{11}月{8}日";let reg = /\{(\d+)\}/g;reg.exec(str);?//?["{2019}",?"2019",?index:?0,?input:?"{2019}年{11}月{8}日",?groups:?undefined]str.match(reg);?//?["{2019}",?"{11}",?"{8}

稍微用心的同學肯定又發現了,多次匹配的情況下,match只能把大正則匹配的內容獲取到,小分組匹配的信息無法獲取。

臥槽?這……呵呵噠,怎么辦?針對這種match無法匹配小括號中的正則的情況,我自己寫了一個函數:

let str = "{2019}年{11}月{8}日";let reg = /\{(\d+)\}/g;let?arrBig?=?[],??//?大正則匹配的內容??arrSmall?=?[],??//?小分組匹配的內容  res = reg.exec(str);    while(res) {  let [big,small] = res;  arrBig.push(big);  arrSmall.push(small);  res = reg.exec(str);}console.log(arrBig, arrSmall);  // ["{2019}", "{11}", "{8}"]   ["2019", "11", "8"]

6-正則分組引用,
一般如果看到兩個一樣,比如:book ,oo 一樣,那么就要考慮正則的分組引用,這里也就看到了分組的第三個作用:分組引用

let?str?=?'book';?// 類似?good?look?moon?foot 這種...let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/; // 分組引用就是通過 "\數字" 讓其代表和對應分組出現一模一樣的內容reg.test(str);?//?=>truereg.test('str');?//?=>falsereg.test('week');?//?=>truereg.test('weeks');?//?=>false

7-正則捕獲的貪婪性:

let str = 'cos2019揚帆2020起航2021';let reg = /\d+/g;str.match(reg);?//?["2019",?"2020",?"2021"]//?我們發現:把所有跟正則匹配的東西都拿到了

我們發現上面的代碼 str.match(reg) 把所有跟正則匹配的東西都拿到了,也就是把像2019這樣的數字整個都拿到了,而不是分開一個一個拿到了 '2', '0', '1', '9' 這樣的單個數字。這是因為正則捕獲的貪婪性。

正則捕獲的貪婪性:默認情況下正則捕獲的時候是按照當前正則所匹配的最長結果來獲取的

這個是正則捕獲的貪婪性。

那么如果我們不希望這樣我們應該怎么做?

可以在量詞元字符后面設置??取消捕獲時候的貪婪性 (按照正則匹配的最短結果來獲取)

reg = /\d+?/g;str.match(reg); //["2", "0", "1", "9", "2", "0", "2", "0", "2", "0", "2", "1"]
*問號在正則中的5大作用:
??? 1- 問號左邊是非量詞元字符:本身代表量詞元字符,出現0-1次
??? 2- 問號左邊出是量詞元字符:取消捕獲時候的貪婪性
??? 3- (?:) 只匹配不捕獲
??? 4- (?=) 正向預查
??? 5- (?!) 負向預查
*小括號用于分組,分組的3個作用:
??? 1- 改變有優先級
??? 2- 分組捕獲
??? 3- 分組引用

四、其他正則捕獲的方法

1- test也能捕獲(本意是匹配)

RegExp.$1~RegExp.$9,獲取當前正則匹配后,第一個到第九個分組的信息

let?str?=?"{2020}年{2}月{28}日";let reg = /\{(\d+)\}/g;reg.test(str);?//?=>?trueRegExp.$1?//?=>?2020reg.test(str);?//?=>?trueRegExp.$1?//?=>?2reg.test(str);?//?=>?trueRegExp.$1?//?=>?28reg.test(str);?//?=>?falseRegExp.$1?//?=>?28??//?這里的28存儲的是上次捕獲的結果

2- replace 字符串中實現替換的方法(一般都是伴隨正則一起使用的)

let?str?=?'cos@2019|cos@2020';?//需求:把'cos' 替換成 'rose'// 1- 不用正則,執行一次只能替換一個str = str.replace('cos','rose'); console.log(str);//rose@2019|cos@2020    //2- 使用正則相對簡單:str = str.replace(/cos/g,'rose'); console.log(str); //rose@2019|rose@2020

3- 但是有些情況不使用正則是搞不定的,正則的優勢凸顯了吧,

//?比如把?cos?==>?cosplaylet str = 'cos@2019|cos@2020'; str = str.replace('cos','cosplay'); //cosplay@2019|cos@2020str = str.replace('cos','cosplay'); //cosplayplayplayplay@2019|cos@2020console.log(str);// 每次都0的位置開始,所以永遠替換掉的是最開始的,類似于正則捕獲的懶惰型
let str = 'cos@2019|cos@2020'; str = str.replace(/cos/g,'cosplay'); // replace不會改變原有字符串console.log(str); // cosplay@2019|cosplay@2020

你看,基于正則可以一次實現。

五、實例

看了這么多東西,是不是有點煩躁了。來吧,看幾個實例。

案例一:把時間字符串進行處理

let?time?=?'2019-11-12';// ==> 變為 2019年11月12日let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;// 這種方法是可以實現的:time = time.replace(reg,'$1年$2月$3日');console.log(time);?//2019年11月12日

還可以這樣處理:
語法, [str].replace([reg],[function])
a-首先拿 reg 和 time 進行正則匹配捕獲,能匹配幾次就會把傳遞的函數執行幾次(而且是匹配一次就執行一次)
b-不僅方法執行,而且 replace 還給方法傳遞了實參信息(其實就是和exec捕獲的內容一致的信息:大正則匹配的內容 和 小分組匹配的信息…)
c- 在函數中,我們返回的是什么,就會把當前大正則匹配的內容替換成什么

...time = time.replace(reg,() => {  // ...});

案例二:對時間字符串進行處理:

let?time?=?"2019-1-15";//?=>?變為2019年1月15日let?reg?=?/^(\d{4})-(\d{1,2})-(\d{1,2})$/;

1- 這樣寫是沒有問題的

time = time.replace(reg,'$1年$2月$3日'); //字符串通過replace如果第一項放入的是正則,那么后面通過$1..可以獲取到分組中的信息console.log(time); //2019年11月15日

2- 還可以這樣寫 [str].replace([reg],[function])
a-首先拿reg 和 time進行匹配捕獲,能匹配幾次就會把傳遞的函數執行幾次(而且是匹配一次,就執行一次)
b-不僅把方法執行了,而且replace還給方法傳遞實參信息(和exec捕獲的內容一致的信息:大正則匹配的內容,小分組匹配的信息,...)
c- 函數中return的是什么,就是把當前大正則匹配結果替換成什么樣

time = "2019-1-15";time = time.replace(reg,(...arg) => {  let [,$1,$2,$3] = arg; ??// 解構賦值第一項是大正則獲取的內容,因為我們不需要所以用?逗號?空出來  $2.length <2 ? $2 = '0' + $2 : null;  $3.length <2 ? $3 = '0' + $3 : null;  return $1+'年'+$2+'月'+$3+'日';}); console.log(time); // 2019年01月15日

案例三:單詞首字母大寫

let?str?=?'good?good?study,?day?day?up!';let reg = /\b([a-zA-Z])[a-zA-Z]*\b/g;// 函數被執行了6次,每次都把正則匹配的信息傳遞給函數str?=?str.replace(reg,?(...arg)?=>?{  let [content,$1] = arg;  $1 = $1.toUpperCase();  content = content.substring(1)  return $1 + content;});console.log(str); // Good Good Study, Day Day Up!

案例四:驗證一個字符串中哪個字母出現的次數最多,多少次?

let str = 'webwangchengbin';

A- 去重思維:

let?obj?=?{};[].forEach.call(str, char => {  if (typeof obj[char] !== 'undefined') {    obj[char] ++;    return;  }  obj[char] = 1;});console.log(obj);    // 通過設置一個最大值的方式let max = 1,  res = [];for (let key in obj) {  let item = obj[key];  item > max ? max = item : null;}console.log('max==>', max); // 3for (let key in obj) {  let item = obj[key];  if (item == max) {    res.push(key);  }}console.log(`出現次數最多的字母是:${res},出現了${max}次`); //出現次數最多的字母是:n,出現了3次

B-排序:

letstr = 'webwangchengbin';str = str.split('').sort((a,b) => a.localeCompare(b)).join('');console.log(str); //abbceegghinnnwwlet reg= /([a-zA-Z])\1+/g;// a--如果只要第一個出現次數最多的字母,不考慮多個字母出現次數相同的情況。:let ary = str.match(reg);console.log(ary); //["bb", "ee", "gg", "nnn", "ww"]ary.sort( (a,b) => b.length - a.length);console.log(ary); // ["nnn", "bb", "ee", "gg", "ww"]console.log(`出現次數最多的字母是:${ary[0].substring(0,1)},出現了${ary[0].length}次`);// b-多個字母出現次數相同:let max = ary[0].length,  res = [ary[0].substring(0,1)];for (let i=1; i  let item = ary[i];  if (item.length < max) {    break;??}  res.push(item.substring(0,1));}console.log(`出現次數最多的字母是:${res},出現了${max}次`)

C-從最大到最小找:

let str = 'webwangchengbinnxxxx',  max = 0,  res = [],  flag = false;str = str.split('').sort( (a, b) => a.localeCompare(b)).join('');console.log(str); //abbceegghinnnnwwxxxxfor (let i=str.length; i>0; i--) {  // /([a-zA-Z])\1{i-1}/ 兩個斜杠之間的都是元字符,如果想把變量的值作為正則的一部分,我們只能用new RegExp() 這種方式  let reg = new RegExp('([a-zA-Z])\\1{'+(i-1)+'}','g'); // 在字符串中一個斜杠表示的是轉義的意思,兩個斜杠才是斜杠的意思  // ==> 上面的正則就是有一個字母,然后重復出現指定次數  str = str.replace(reg, (content,$1) => {    res.push($1);    max = i;    flag = true;  });  // 只要能夠進入這個函數,就應該結束循環,所以我們再定義一個變量  if (flag) break;}console.log(`出現次數最多的字母是:${res},出現了${max}次`); //出現次數最多的字母是:n,x,出現了4次

案例五:時間字符串格式化

比如:
從服務器獲取的格式:
????? '2019-11-19 15:39:5'
????? '2019/11/19 15:39:5'
想要轉化為:
????? 11月19日 15時39分
????? 2019年11月19日

~?function?()?{???// formatTime?時間字符串的格式化處理方法       function formatTime() {      // 1-首先獲取事件字符串中的年月日等信息             let timeAry = this.match(/\d+/g);      // 因為調用的時候是  time.formatTime()這種形式, 所以this就是我們的  formatTime      let template = '{0}年{1}月{2}日 {3}時{4}分{5}秒';      template = template.replace(/\{(\d+)\}/g, (content, $1) => {        // => content: 當前本次大正則匹配的信息        // => $1: 本次小分組單獨匹配的信息????????//?以$1的值作為索引,到timeAry中找到對應的時間????????let?time?=?timeAry[$1]?||?'00';?//?如果沒有時分秒?那么我們會得到undefined,這個時候我就用?00?表示????????time.length?2???time?=?        return time;      });      return template;    }    // 擴展到內置類 String.prototype上  如果擴展的比較多的話就這么寫,否則就按照正常的擴展就行了    ['formatTime'].forEach(item => {      // String.prototype['formatTime'] = 'formatTime' // 右邊的不能是字符串必須是個方法才可以,所以用eval轉化一下      String.prototype[item] = eval(item);    });  }();let time = '2019-11-19 15:39:5';console.log(time.formatTime()); //2019年11月19日 15時39分05秒

看起來很完美對嗎?但是現在輸出的格式是固定的,我們希望這個格式可以由用戶來控制。如果這個格式用戶沒有傳遞,那么我們就使用默認的這個固定格式。

~?function?()?{  /* @params:    template: [string] 我們最后期望獲取的日期格式的模板    模板規則: {0}=>年 {1}=>月 {2}=>日 {3}=>時 {4}=>分 {5}=>秒    @return      [string]格式化后的時間字符串      by WangYuxi on 2019/11/19  */  function formatTime(template = '{0}年{1}月{2}日 {3}時{4}分{5}秒') {    let timeAry = this.match(/\d+/g);    return template = template.replace(/\{(\d+)\}/g, (...[, $1]) => {      let time = timeAry[$1] || '00';       return time.length < 2 ? '0' + time : time;    });  }  ['formatTime'].forEach(item => {    String.prototype[item] = eval(item);  });}();let time = '2019-11-19 15:39:5';console.log(time.formatTime()); //2019年11月19日 15時39分05秒console.log(time.formatTime('{1}月{2}日 {3}:{4}')); //11月19日 15:39console.log(time.formatTime('{1}-{2} {3}:{4}')); //11-19 15:39console.log(time.formatTime('{0}年{1}月{2}日')); //2019年11月19日time = '2019-11-19';console.log(time.formatTime()); //2019年11月19日 00時00分00秒

案例六:對url地址進行處理:

 ~function() {   /*     queryURLParams: 獲取URL地址問號后面參數的值,(可能也包含hash值)    @params:    @return:      [object] 把所有參數以鍵值對的方式存儲起來并且返回    */    function queryURLParams() {      let obj = {};      this.replace(/([^?=]+)=([^?=]+)/g, (...[, $1, $2]) => obj[$1] = $2);      this.replace(/#([^?=]+)/g, (...[,$1]) => obj['HASH'] = $1);      return obj;    }    ['formDate','queryURLParams'].forEach( item => {      String.prototype[item] = eval(item);    })}();  let time = '2019-11-19 19:22:3';console.log(time.formDate());let url = 'http://www.cos.cn/?lx=1&from=wx#video';// ==> {lx:1,form:'wx',hash:'video'}console.log(url.queryURLParams()); //{lx: "1", from: "wx", HASH: "video"}  

案例七:千分符

A- 不用正則:把字符串倒過來處理

let num = '1123456789'; //'1,123,456,789' 千分符num = num.split('').reverse().join('');for (let i=2; i-1; i+=    let prev = num.substring(0, i+1),        next = num.substring(i+1);    num = prev + ',' + next;}num = num.split('').reverse().join('');console.log('===>', num); // ===> 1,123,456,789

B-正則:

~function()?{  /* millimeter: 實現大數字的千分符處理    @params    @return      [string] 千分符后的字符串   */  function millimeter() {    return this.replace(/\d{1,3}(?=(\d{3})+$)/g, content => content + ',');  }  ['formDate', 'queryURLParams', 'millimeter'].forEach( item => {    String.prototype[item] = eval(item);  })}();let num = '1123456789'; //'1,123,456,789' 千分符console.log(num.millimeter());

吐血嗎?正則會這么多,可以滿足你日常工作和面試大部分的需求了。

相信能看到這里的人也很少。隨意隨意:-)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446128.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446128.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446128.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言深度剖析書籍學習記錄 第四章 指針和數組

p 稱為指針變量,p 里存儲的內存地址處的內存稱為 p 所指向的內存。 指針變量 p 里存儲的任何數據都將被當作地址來處理一個基本的數據類型(包括結構體等自定義類型)加上“*” 號就構成了一個指針類型的模子。這個模子的大小是一定的&#xff0c;與“*”號前面的數據類型無 關。…

js中select下拉框重置_如何利用CSS3制作炫酷的下拉框

很多小伙伴都不清楚CSS3是做什么&#xff1f;用途是什么&#xff1f;接下來我就給展示一個css3制作一個炫酷下拉框。其實不只是這些&#xff0c;還有很多。CSS3是CSS(層疊樣式表)技術的升級版本&#xff0c;于1999年開始制訂&#xff0c;2001年5月23日W3C完成了CSS3的工作草案&…

select選擇框必輸校驗_輪子這么多,我們為什么選擇自研NewSQL

作者介紹李鑫&#xff0c;滴滴資深軟件開發工程師&#xff0c;多年分布式存儲領域設計及開發經驗。曾參與NoSQL/NewSQL數據庫Fusion、分布式時序數據庫sentry、NewSQL數據庫SDB等系統的設計開發工作。一、背景Fusion-NewSQL是由滴滴自研的在分布式KV存儲基礎上構建的NewSQL存儲…

C語言深度剖析書籍學習記錄 第五章 內存管理

常見的內存錯誤 定義了指針變量&#xff0c;但是沒有為指針分配內存&#xff0c;即指針沒有指向一塊合法的內存。 結構體成員指針未初始化 很多初學者犯了這個錯誤還不知道是怎么回事。這里定義了結構體變量 stu&#xff0c;但是他沒 想到這個結構體內部 char *name 這成員在定…

怎么改電腦網絡ip地址_拋棄重啟路由器獲取ip地址方式,巧妙運用ip代理改IP工具...

網絡是簡單的也是復雜的&#xff0c;在如此龐大的網絡世界里有太多的不確定因素&#xff0c;導致我們遇到IP限制問題&#xff0c;從而影響到我們的網絡訪問&#xff0c;而大家都知道&#xff0c;如果遇到ip被限制的問題&#xff0c;最快速直接的辦法就是把被限制的ip更換一個新…

C語言深度剖析書籍學習記錄 第六章 函數

函數的好處 1、降低復雜性:使用函數的最首要原因是為了降低程序的復雜性&#xff0c;可以使用函數來隱含信息&#xff0c;從而使你不必再考慮這些信息。2、避免重復代碼段:如果在兩個不同函數中的代碼很相似&#xff0c;這往往意味著分解工作有誤。這時&#xff0c;應該把兩個…

如何把word分裝到兩個byte_如何核對兩個Word文檔的內容差別?同事加班半小時,我只花了30秒...

昨天下班前&#xff0c;老板突然發了兩份Word文檔過來&#xff0c;一份是原稿&#xff0c;還有一份是修訂稿&#xff0c;叫我們找出兩份文檔的內容差別之處&#xff0c;我只花了30秒就搞定了&#xff0c;然后準時下班&#xff01;你想知道我是怎么操作的嗎&#xff1f;下面小源…

stm32f767中文手冊_ALIENTEK 阿波羅 STM32F767 開發板資料連載第五章 SYSTEM 文件夾

1)實驗平臺&#xff1a;alientek 阿波羅 STM32F767 開發板2)摘自《STM32F7 開發指南(HAL 庫版)》關注官方微信號公眾號&#xff0c;獲取更多資料&#xff1a;正點原子第五章 SYSTEM 文件夾介紹第三章&#xff0c;我們介紹了如何在 MDK5 下建立 STM32F7 工程。在這個新建的工程之…

手機安卓學習 內核開發

官網開源代碼 Documentation - MiCode/Xiaomi_Kernel_OpenSource - Sourcegraph Xiaomi 11T Pro GitHub - MiCode/Xiaomi_Kernel_OpenSource: Xiaomi Mobile Phone Kernel OpenSourceAndroid 開源項目 | Android Open Source Project google安卓官網 目錄概覽 參考…

vs 啟動調用的目標發生異常_如何解決不可測、異常場景的問題?

阿里QA導讀&#xff1a;在軟件研發過程中&#xff0c;發布前跨多個系統的聯調測試是不可或缺的一環&#xff0c;而在聯調過程中&#xff0c;經常會遇到一些比較棘手的困難&#xff0c;阻塞整個聯調進程。其中比較典型的有&#xff1a;第三方的研發節奏不一致&#xff0c;導致無…

Linux內核 scatterlist介紹

scatterlist 物理內存的散列表。通俗講&#xff0c;就是把一些分散的物理內存&#xff0c;以列表的形式組織起來 誕生背景 假設有三個模塊可以訪問memory&#xff1a;CPU、DMA控制器和某個外設。CPU通過MMU以虛擬地址&#xff08;VA&#xff09;的形式訪問memory&#xff1b;…

www.python123.org_python爬蟲-requests

Requests庫是目前常用且效率較高的爬取網頁的庫1.一個簡單的例子import requests #引入requests庫r requests.get("http://www.baidu.com")  #調用get方法獲取界面print(r.status_code)    #輸出狀態碼print(r.text)    #輸出頁面信息通過以下代碼&#x…

Linux內核 crypto文件夾 密碼學知識學習

密碼算法分類 對稱算法非對稱算法消息摘要&#xff08;單向哈希&#xff09;算法這些算法作為加密函數框架的最底層&#xff0c;提供加密和解密的實際操作。這些函數可以在內核crypto文件夾下&#xff0c;相應的文件中找到。不過內核模塊不能直接調用這些函數&#xff0c;因為…

python隨機出100道加法題_自動出題隨機100題-20以內加減法全部算式

班 級:姓 名:12-819-411-1114-1018-111417-261215-113-417-819-1914-341516-31269619-161159312817-014-1414-1112-501414-017-616-111-012-211520-711113051019-1810619-691118-1220-519-818018114-1416-712-1015-1319-916-714-920-717-118-1611-815-416-1014-919-416-1413-…

Linux crypto相關知識的匯總 Linux加密框架crypto中的算法和算法模式(一)

Linux加密框架中的算法和算法模式 Linux加密框架中的算法和算法模式&#xff08;一&#xff09;_家有一希的博客-CSDN博客 加密框架支持的密碼算法主要是對稱密碼算法和哈希算法&#xff0c;暫時不支持非對稱密碼算法。除密碼算法外&#xff0c;加密框架還包括偽隨機數生成算法…

python3.5.2安裝pygame_【閑來無事,py寫game】Mac-Python3.5安裝pygame 1.9.2 小計

13正文之前沒錯&#xff0c;我就是這么不學無術&#xff0c;C實在學的雞兒疼&#xff0c;所以干脆搞點娛樂措施&#xff0c;昨天趕上了京東圖書做大活動&#xff0c;所以屯了一批書&#xff0c;好久沒碰python了。所以就整本玩玩&#xff01;今天這不就上手了么&#xff01;自己…

Linux crypto相關知識的匯總 Linux加密框架crypto對稱算法和哈希算法加密模式

參考鏈接 Linux加密框架中的算法和算法模式&#xff08;二&#xff09;_家有一希的博客-CSDN博客 對稱算法 分組算法模式 ECB模式 ECB模式下&#xff0c;明文數據被分為大小合適的分組&#xff0c;然后對每個分組獨立進行加密或解密如下圖所示如果兩個明文塊相同&#xff0c…

物化視圖和視圖的最大區別_基于catalyst的物化視圖改寫引擎的實現

更新日志&#xff1a;1. 2020/06/16 group by 視圖的部分描述錯誤&#xff0c;已修正。什么是物化視圖我先用我的話解釋一下什么是物化視圖。假設我們已經有A&#xff0c;B兩張表&#xff0c;現在我創建了一張表C,C是由A,B兩張表經過一條SQL處理得到的&#xff0c;這個時候我們…

Linux加密框架中的算法和算法模式

參考鏈接 Linux加密框架中的算法和算法模式&#xff08;三&#xff09;_家有一希的博客-CSDN博客 對稱算法 14 如上所示&#xff0c;在arc4.c中定義了兩個與RC4算法相關的算法實現&#xff0c;分別為arc4和ecb(arc4)&#xff0c;其中arc4是RC算法的算法實現&#xff0c;而ecb…