Regular expression

It seems that we don’t use regulars much in our work, which may be because regulars are too abstract and not easy to remember and understand, so we don’t use them much. However, regulars can quickly realize our functions. In our work, forms need to do a lot of verification, so using regulars will indeed bring us a lot of convenience

regular expression : RegExp

Rules for handling strings

  1. You can only handle strings

  2. A rule: you can either verify that a string matches a rule (test) or capture the content of a string that matches a rule (exec/match…).

Create a way

// Create a literal (the metacharacter that describes the rule is between two slashes)
let reg1 = /\d+/;
// Constructor creation (two arguments: metacharacter string modifier string)
let reg2 = new RegExp("\\d+");
Copy the code
/ / the difference between
//1. Since the constructor is passing a string, \ needs two slashes to represent it
let reg = /\d+/g;
let reg1 = new RegExp("\\d+"."g");
//2. The metacharacter between the two slashes describes the rule. If there are variables, the constructor method is required
let type = "majun"
let reg2 = /^@"+type+"@$/
console.log(reg2.test("@majun@")) //false
console.log(reg2.test('@"""typeeee"@')) //true
let reg3 = new RegExp("^ @"+type+"@ $")
console.log(reg3.test("@majun@")) //true
Copy the code

Regular expression components (metacharacter modifiers)

metacharacters1.Number of occurrences of quantifier metacharacter Settings *0To many times +1To many times?0or1Times {n} n times {n,} n to many times {n,m} n to m times2.Special metacharacters represent special meanings individually or in groups; escape characters (ordinary -> special -> ordinary). Any character other than \n (newline) ^ Start $end \n newline \d0-9\D \W alphanumeric _ \W \S Blank characters (Spaces, tabs, page feeds, etc.) \S \ T TAB character (a TAB key: Four Spaces) x | y x or y \ b border [xyz] x or y, or z [^ xy] in addition to the x y [a-z] of arbitrary characters [a-z this range specified0-9a-za-z_] === \w [^a-z] () grouping (? :) only matches but does not capture (? =) forward check (? !). Negative lessons3.Normal metacharacter: represents its own meaning /mj/ matches is"mj"
Copy the code
The modifier1.I ignoreCase ignores case matching2.M multiline can match multiple lines3. g  globalThe global matchingCopy the code

Metacharacter detailed parsing

^ $

let reg = /^\d/
console.log(reg.test("mj"))  //false
console.log(reg.test("2021mj"))  //true

let reg1 = /\d$/
console.log(reg1.test("mj"))  //false
console.log(reg1.test("mj2021"))  //true

// Do not include
let reg2 = /\d+/
// Add strings only if they are consistent with the rule
let reg3 = /^\d+$/
console.log(reg3.test("1mj2"))  //false
console.log(reg3.test("12"))  //true
Copy the code

\

//. Represents any character except \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
// Based on the escape character \. Represents the decimal point
let reg1 = $/ / ^ 2 \. 3;
console.log(reg1.test("2.3")); //true
console.log(reg1.test("2 @ 3")); //false
Copy the code
let str = "\\d";
let reg = /^\d$/;
console.log(reg.test(str)) //fasle
reg = /^\\d$/
console.log(reg.test(str)) //true
Copy the code

x|y

ler reg = 18 | $29 / / ^;
console.log(reg.test("18")) //true
console.log(reg.test("29")) //true
console.log(reg.test("189")) //true
console.log(reg.test("129")) //true
console.log(reg.test("1829")) //true
console.log(reg.test("829")) //true
console.log(reg.test("182")) //true
/ / direct x | y will mess priority problems, general grouping with parentheses
reg = $/ / ^ 18 | (29);
/ / 18 29
Copy the code

[xyz]

// The characters in brackets usually represent their own meanings
let reg = / ^ @ + $/;
console.log(reg.test("@")) //true
console.log(reg.test("+")) //true
console.log(reg.test("@ @")) //false
console.log(reg.test("@ +")) //false

reg = /^[\d]$/;
console.log(reg.test("\ \")) //false
console.log(reg.test("d")) //false
console.log(reg.test("9")) //true

reg = /^[\\d]$/;
console.log(reg.test("\ \")) //true
console.log(reg.test("d")) //true
console.log(reg.test("9")) //false

// The brackets have only one digit
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
Copy the code

Common regular expressions

  1. Is it a significant number
/* * * may appear + -, may not appear * * a bit of 0-9 can be used, most of the first can not be 0 * the decimal part may not have, once there must be a decimal point + number */
reg = / ^ (+ -)? (\d|([1-9]\d+))(\.\d+)? $/
Copy the code
  1. Verify password
// Alphanumeric underscore
/ / 6 to 16
let val = userPassInp.value
let reg = / 16th {6} \ w /
let flag = reg.test(val)

function checkpass () {
    if(val.length < 6 || val.length > 16){
        flag = false
        return 
    }
    let area = ['a'.'b'. .'_']
    for(let i=0; i<val.length; i++){if(! area.includes(val[i])){return flag = false}}}Copy the code
  1. Verify real name
Chinese characters / / * * ^ [\ u4E00 - \ u9FA5] $2-10 * / * name length may have translation, the Chinese character (· [\ u4E00 - \ u9FA5] {2, 10})} {0, 2 * /
reg = / ^ [\ u4E00 - \ u9FA5] {2, 10} (. [\ u4E00 - \ u9FA5] {2, 10})} {0, 2 $/
Copy the code
  1. Validation email
reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/

// \w+((-\w+)|(\.\w+))*
// 1. Start with alphanumeric underscore (1 to multiple times)
// 2. It can also be - alphanumeric underscore or. Alphanumeric underscore all 0 to multiple times
// The name of the mailbox consists of alphanumeric underscores -., but -/. Does not occur consecutively and does not begin

// @[A-Za-z0-9]+
// 1. @ followed by: numeric letter (1 to multiple times)

// ((\.|-)[A-Za-z0-9]+)*
// 1. Add the name after @

// \.[A-Za-z0-9]+
// 1. @xxx.com @xxx.cn this match is the final domain name (.com/com/.org/.edu/.net)

[email protected]
[email protected]
Copy the code
  1. Verify ID card
// the last digit may be X
// Top six provinces and counties
// The middle eight digits are year, month and day
/ / the last four last: X | \ d followed: an odd number of men and women even The rest through the algorithm
let reg = /^\d{17}(\d|X)$/
// The second function of the bracketing group is group capture
reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/
reg.exec('421127199504130075') //["421127199504130075", "421127", "1995", "04", "13", "7", "5", index: 0, input: "421127199504130075", groups: undefined]
Copy the code

Capture of re

A method to achieve regex capture

  • Method on RegExp. Prototype

    exec

    test

  • The String string. prototype supports regular expression handling methods

    replace

    match

    split

    .

/* * The result is null or an array * the first item: the matched content * the remaining items: the matched content of the corresponding group * index: the initial index of the matched content * input: the original string value * 2. Each time an exec is executed, it can only catch one match to the regular rule, which is the first one (the laziness of regular capture) */
let str = "majun2021up2022up2023";
let reg = /\d+/;
console.log(reg.exec(str)) //['2021',index: 5, input: 'majun2021up2022up2023', groups: undefined]

// To achieve the re capture, the re and the string must match, and null is returned if the re does not match
let reg = /^\d+$/;
console.log(reg.test(str)) //false
console.log(reg.exec(str)) //null
Copy the code
// The reason is lazy
// Reg. lastIndex The default starting index for the next match of the reg.lastIndex is 0
let str = "majun2021up2022up2023";
let reg = /\d+/;
console.log(reg.lastIndex) / / 0
console.log(reg.exec(str)) / / / '2021'...
console.log(reg.lastIndex) / / 0
Copy the code

Even if you change lastIndex manually, it doesn’t work. You can add the modifier G. By default, the browser will change lastIndex

Next, implement an execAll method that captures all matches at once

(function(){
    RegExp.prototype.execAll = function execAll (str) {
        // STR is the string to match
        // this re instance
        // Prevent an infinite loop for the first item in the array without adding g
        if(!this.global) return this.exec(str) 
        let resultArr = [],
            res = this.exec(str);
        while (res) {
            // Continue capturing as long as the captured content is not null
            resultArr.push(res[0])
            res = this.exec(str);
        }
        return resultArr
    }
})()
Copy the code

The match method of the string captures everything

Group capture of re

(? 🙂 only match not capture, capture the same status as the one above, because \ | X d a group change priority, lead to packet capture

let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/
console.log(reg.exec('421127199504130075')) //["421127199504130075", "421127", "1995", "04", "13", "7", "5", index: 0, input: "421127199504130075", groups: undefined]
console.log('421127199504130075'.match(reg)) //["421127199504130075", "421127", "1995", "04", "13", "7", "5", index: 0, input: "421127199504130075", groups: undefined]

let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(? :\d|X)$/
console.log(reg.exec('421127199504130075')) //["421127199504130075", "421127", "1995", "04", "13", "7", index: 0, input: "421127199504130075", groups: undefined]
console.log('421127199504130075'.match(reg)) //["421127199504130075", "421127", "1995", "04", "13", "7", index: 0, input: "421127199504130075", groups: undefined]
Copy the code

If g is not set to match only once, the result obtained by exec and match is the same (both large re matches and small group matches).

let str = "{0} Year {1} Month {2} day"
let reg = /\{(\d+)\}/
console.log(reg.exec(str)) / / / "{0}", "0", the index: 0, input: "{0} on {1} {2}", groups: undefined]
console.log(str.match(reg)) / / / "{0}", "0", the index: 0, input: "{0} on {1} {2}", groups: undefined]
Copy the code

G exec can only be set one at a time, but match can capture all of them, but the problem is that small groups are not captured

let str = "{0} Year {1} Month {2} day"
let reg = /\{(\d+)\}/g
console.log(reg.exec(str)) / / / "{0}", "0", the index: 0, input: "{0} on {1} {2}", groups: undefined]
console.log(str.match(reg)) / / / "{0}", "{1}", "{2}"]

let aryBig = [],
    arySmall = [],
    res = reg.exec(str)
while (res) {
    let [big, small] = res
    aryBig.push(big)
    arySmall.push(small)
    res = reg.exec(str)
}
Copy the code

A grouped reference to a re

let str = "good"; // book foot seek look
let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/
Copy the code

Cupidity of regular capture

Greedy: When a re is captured, it is matched with the longest current re match

let str = "majun2021up2022up2023"
let reg = /\d+/g
console.log(str.match(reg)) / / / "2021", "2022", "2023"]

reg = /\d+? /g
console.log(str.match(reg)) / / / "2", "0", "2", "1", "2", "0", "2", "2", "2", "0", "2", "3"]
Copy the code

People can not be like regular, lazy and greedy

Other capture methods

test

Matches from the left side of the string to a character that matches the regular rule, return true, otherwise return false. Similarly, test under the g modifier changes the value of lastIndex

Return false if test matches to the end or does not, and if successful add the current subgroup to the array to match the contents of the first element. Constructor for RegExp exists $1-$9, which refer specifically to the first through ninth captured contents of the current subgroup

replace

Replace the STR string method. The replace (STR | reg, STR | function)

let time = "2021-04-28"
let reg = / ^ (\ d {4}) - (\ d {1, 2}) - $/ (\ d {1, 2})
time = time.replace(reg, "$1 year $2 month $3")
console.log(time) //" April 28, 2021"

time = "2021-04-28"
time = time.replace(reg, (big,$1, $2, $3) = >{
    console.log(big,$1, $2, $3) / / 2021 04 28 2021-04-28
    return "$1 year $2 month $3"
})
console.log(time) //" April 28, 2021"
Copy the code
// Capitalize the first letter of the word
let str = "good good study, day day up"
let reg = /\b([a-zA-Z])[a-zA-Z]*\b/g
str = str.replace(reg, (. arg) = >{
    let [big, $1] = arg
    return  $1.toUpperCase() + big.substring(1)})Copy the code
// Which letter in the string appears the most times and how many times?
let str = "abcgajgajjagjlagj"
let obj = {}
let str1 = [...str]
str1.forEach(item= >{
    if(obj.hasOwnProperty(item)) {
        obj[item]++
        return
    }
    obj[item] = 1
})
console.log(obj) //{a:5,b:1,c:1,g:4,j:5,l:1}
let max = -Infinty;
for(let key in obj){
    obj[key] > max ? max=obj[key] : null
}
let res = []
for(let key in obj){
    if(obj[key]===max){
        res.push(key)
    }
}
console.log('Most of all${res}.${max}Time `)

// -----------------------
let str = "abcgajgajjagjlagj"
let str1 = [...str]
str1 = str1.sort((a,b) = >a.localeCompare(b)).join(' ')
//str1 = str1.sort().join('')
let reg = /([a-zA-Z])\1*/g
let ary = str1.match(reg).sort((a,b) = >b.length - a.length)
console.log(ary) //["aaaaa", "jjjjj", "gggg", "b", "c", "l"]
let max = ary[0].length
let res = [ary[0].substr(0.1)]
for(let i=1; i<ary.length; i++){if(ary[i].length < max) {
        break
    }
    res.push(ary[i].substr(0.1))}console.log('Most of all${res}.${max}Time `)

// --------------------

let str = "abcgajgajjagjlagj"
let str1 = [...str]
str1 = str1.sort((a,b) = >a.localeCompare(b)).join(' ')
let max = 0,
    res = [],
    flag = false;
for(leti=str1.length; i>0; i--){let reg = new RegExp("([a-zA-Z])\\1{" + (i-1) + "}"."g")
    str1.replace(reg, (content,$1) = >{
        res.push($1)
        max=i
        flag = true
    })
    if(flag) break
}
console.log('Most of all${res}.${max}Time `)
Copy the code

Common regular processing

~function () {
    function formatTime(template = "{0} year {1} month {2} day {3} {4} minutes {5} seconds") {
        let ary = this.match(/\d+/g);
        template = template.replace(/\{(\d+)\}/g.(. arg) = >{
            let [, $1] = arg
            let time = ary[$1] | |'00'
            // time = time.length < 2 ? '0' + time : time
            time.length < 2 ? time = '0' + time : null
            return time
        })
        return template
    }
    function queryURLParams() {
        let res = {}
        this.replace(/([^?=&#]+)=([^?=&#]+)/g.(. [, $1, $2]) = >{
            res[$1] = $2
        })
        this.replace(/#([^?=&#]+)/g.(. [, $1]) = >{
            res['hash'] = $1
        })
        return res
    }
    function millimeter() {
        return this.replace(/ \ d {1, 3} (? =(\d{3})+$)/g.content= >{
            return content + ","})} ['formatTime'.'queryURLParams'.'millimeter'].forEach(item= >{
        String.prototype[item] = eval(item)
    })
}()
var a = "The 2021-4-28-15-25-1"
console.log(a.formatTime()) // 15:25:01 on 28 April 2021
console.log(a.formatTime("{0} / {1} {2} {3} {4} / {5}")) / / 2021/04/28 15/25/01
var b = "https://www.baidu.com?m=1&j=2#pathName"
console.log(b.queryURLParams()) //{m: "1", j: "2", hash: 29}
var c = "12345678"
console.log(c.millimeter()) //12,345,678
Copy the code