Regular expression

Regular expression: the RegExp

Rules for handling strings

  • You can only handle strings
  • It is a rule: you can either verify that a string conforms to a rule (test) or capture the content of a string that conforms to the rule (exec/match…).
let str = 'good good study , day day up!';
//=> Learning regularity is to make rules (including numbers)
let reg = /\d+/;
reg.test(str); //=>false

str = '2019-08-12';
reg.exec(str); //=>["2019",index:0,inputs:" primitive string "]
Copy the code

Writing regular expressions

There are two ways to create it

//=> literal creation method (two slashes are wrapped between each other, which are used to describe the rule's metacharacters)
let reg1 = /\d+/;

//=> Constructor mode creates two arguments: metacharacter string, modifier string
let reg2 = new RegExp('\\d+');
Copy the code

A regular expression consists of two parts

  • metacharacters
  • The modifier
/* Common metacharacter */
//=>1. Set the number of occurrences of quantifier metacharacters* Zero to multiple + one to multiple? Zero or one {n} occurs n times {n,} occurs n to many {n,m} occurs n to m times//=>2. Special metacharacters: a single metacharacter or a combination of metacharacters indicates a special meaning\ escape character (normal -> special -> normal). Any character other than \n (newline) ^ which metacharacter to start with $which metacharacter to end with \n newline \d0~9Between a number \D not0~9A digit between (uppercase and lowercase mean opposite) \w Any character in digits, letters, and underscores \s a whitespace character (including Spaces, tabs, page breaks, etc.) \t a TAB character (a TAB key: Four Spaces) \ b matches a word boundary x | y x or y [xyz] a character in a character in x or y, or z [^ xy] any character other than x/y [a-z] of arbitrary characters [a-z this range specified0-9a-za-z_]===\w [^a-z] ===\w [^a-z] :) only matches but does not capture (? =) forward check (? !). Negative lessons//=>3. Common metacharacter: indicates its own meaning/xiaoming/ This regex matches"xiaoming"
Copy the code
/* Regular expression modifiers: img*/I =>ignoreCase ignores word case matching m =>multiline can match multiple lines g =>globalThe global matching/* /A/.test('lalala') =>false /A/i.test('lalala') =>true */
Copy the code

Metacharacter detailed parsing

^ $

let reg = /^\d/;
console.log(reg.test('xiaoming')); //=>false
console.log(reg.test('2019xiaoming')); //=>true
console.log(reg.test('xiaoming2019')); //=>false
Copy the code
let reg = /\d$/;
console.log(reg.test('xiaoming')); //=>false
console.log(reg.test('2019xiaoming')); //=>false
console.log(reg.test('xiaoming2019')); //=>true
Copy the code
//=>^/$Do not add either: The string contains the content that complies with the rules
let reg1 = /\d+/;
//=>^/$Add both: the string must be consistent with the rule
let reg2 = /^\d+$/;

//=> Example: verify mobile phone number (11 digits, the first digit is 1)
let reg = /^1\d{10}$/;
// /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
Copy the code

\

//=>. Is not a decimal point, is 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, so that it can only represent the decimal point
reg = $/ / ^ 2 \. 3;
console.log(reg.test('2.3')); //=>true
console.log(reg.test('2 @ 3')); //=>false

let str = '\\d';
reg = /^\d$/; //=>\d represents the numbers from 0 to 9
console.log(reg.test(str)); //=>false
reg = /^\\d$/; //=> Convert special coincidence to normal
console.log(reg.test(str)); //=>true
Copy the code

x|y

let reg = 18 | $29 / / ^;
console.log(reg.test('18')); //=>true
console.log(reg.test('and')); //=>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
/ / -- - direct x | y will mess priority problems, normally we write is accompanied by grouping parentheses, because parentheses change processing priority = > parentheses: grouping
reg = $/ / ^ 18 | (29);
console.log(reg.test('18')); //=>true
console.log(reg.test('and')); //=>true
console.log(reg.test('129')); //=>false
console.log(reg.test('189')); //=>false
//=> Can only be 18 or 29
Copy the code

[]

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

reg = /^[\d]$/; //=>\d in brackets is still 0-9
console.log(reg.test('d')); //=>false
console.log(reg.test('\ \')); //=>false
console.log(reg.test('9')); //=>true

//2. There are no multiple digits in brackets
reg = $/ / ^ [18];
console.log(reg.test('1')); //=>true
console.log(reg.test('8')); //=>true
console.log(reg.test('18')); //=>false

reg = $/ / ^ [10-29]; //=>1 or 0-2 or 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
Copy the code

Common regular expressions

  1. Verifies whether it is a significant number

    /* * Rule analysis * 1. The +- sign may or may not occur. * 2. A 0-9 can, more than the first can't is 0 (\ d | (1-9] [\ d +)) * 3. May or may not have a decimal part, but must be followed by a decimal point + number (\.\d+)? * /
    let reg = / ^ (+ -)? (\d|([1-9]\d+))(\.\d+)? $/;
    Copy the code
  2. Verify password

    //=> Digits, letters, and underscores (_)
    / / = > 6 ~ 16
    let val = userPassInp.value,
        reg = 16th {6} $/ ^ \ w /;
    let flag = reg.test(val);
    / * function checkPass (val) {if (val. Length < 6 | | val. The length > 16) {alert (' length must be between 6 and 16! '); return; } let area=['a','b'....'_']; //=> Contains digits, letters, and underscores. For (let I =0; i
    Copy the code
  3. Verify real name

    /^[u4E00-\u9FA5]$/ * 2 Name length 2 ~ 10 * 3. There may be translation, the Chinese character (· [\ u4E00 - \ u9FA5] {2, 10})} {0, 2 * /
    let reg = / ^ [\ u4E00 - \ u9FA5] {2, 10} (· [\ u4E00 - \ u9FA5] {2, 10})} {0, 2 $/;
    Copy the code
  4. Authenticating mailbox

    let 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 digits)
    //2. Can also be - alphanumeric underscore or. Alphanumeric underscore, overall zero to multiple times
    //=> The mailbox name can contain digits, letters, underscores (_), hyphens (-), and. Several components, but -/. Does not occur consecutively or as a starting point
    
    //=> @[A-Za-z0-9]+
    //1.@ followed by: number, letter (1-bit)
    
    //=> ((\.|-)[A-Za-z0-9]+)*
    //1. Add the name after @
    // multiple domains
    // Enterprise email [email protected]
    
    //=> \.[A-Za-z0-9]+
    / / 1. The match is the final domain name (com/.cn/.org/.edu/.net.)
    Copy the code
  5. Id Card Number

    * * * * * * * * * * * * * * * * * * * * * * * * * * * The last digit => X or number * the penultimate digit => even female odd male * The rest is calculated by the algorithm */
    //let reg = /^\d{17}(\d|X)$/;
    //=> The second function of the bracketing group: group capture, not only can capture the information of the large re match, but also can capture the content of each small group separately
    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"...]. The result of the capture is an array containing the contents of each small group individually retrieved
    
    Copy the code

Capture of re

A way to achieve regex capture

  • Method on RegExp. Prototype

    • exec
    • test
  • The String string. prototype supports regular expression handling methods

    • replace
    • match
    • splite
    • .
let str = 'xiaoming2019yangfan2020qihang2021';
let reg = /\d+/;
The result of the capture is null or an array * first item: the content captured this time * Remaining items: the content captured separately in the corresponding small group * index: the initial index of the current captured content in the string * input: the original string * 2. For each exec execution, only one match can be caught, but by default, we execute a hundred times, and the result is always the first match, the rest of the catch is not * => "lazy" : the default catch is only the first */
console.log(reg.exec(str)); //=>["2019", index: 7, input: "xiaoming2019yangfan2020qihang2021"]
console.log(reg.exec(str)); / / = > [...] of "2019"

Let reg = /^\d+$/; let reg = /^\d+$/; console.log(reg.test(str)); //=>false console.log(reg.exec(str)); //=>null */
Copy the code

Lazy solutions

let str = 'xiaoming2019yangfan2020qihang2021';
/* * reg.lastIndex: the starting index position of the current re for the next match * reason for lazy capture: by default, the value of lastIndex is not changed, each time it is looked up from the beginning of the string, so it always finds the first * solution: the global modifier g */
// let reg = /\d+/;
// console.log(reg.lastIndex); //=>0 the following matches are caught starting at STR index zero
// console.log(reg.exec(str));
// console.log(reg.lastIndex); //=>0 when the first match is caught, lastIndex remains unchanged, so exec will always find the first match from the beginning of the string

// let reg = /\d+/g;
// console.log(reg.exec(str)); / / = > [...] of "2019"
// console.log(reg.lastIndex); //=>11 After setting the global matching modifier g, lastIndex will change itself after the first match
// console.log(reg.exec(str)); / / = > [...] of "2020"
// console.log(reg.lastIndex); / / = > 22
// console.log(reg.exec(str)); / / = > [...] of "2021"
// console.log(reg.lastIndex); / / = > 32
// console.log(reg.exec(str)); //=>null The result of the next capture is null, but the lastIndex returns to the original value of zero, and the next capture starts from the first one...
// console.log(reg.lastIndex); / / = > 0
// console.log(reg.exec(str)); / / = > [...] of "2019"

// let reg = /\d+/g;
// if (reg.test(str)) {
// //=> Verify: only re and string matches we are capturing
// console.log(reg.lastIndex); //=>11 After the TEST match validation, LASTINDEX has been modified to the result of the first match, so the next capture will not start from scratch
// console.log(reg.exec(str)); / / = > [...] of "2020"
// }

//=> Required: Write a method execAll that can be executed once to capture the results of all matches (the preconditioned re must be set to the global qualifier g)~ (function () {
    function execAll(str = ' ') {
        //=> STR: string to be matched
        //=>this: instance of RegExp (regex for current operation)
        //=> The first thing to do is to verify that the current re is set to G. If G is not set, the loop cannot be captured again. Otherwise, it will cause an infinite loop
        if (!this.global) return this.exec(str);
        // ARY stores all the last captured information RES stores the contents of each capture (array)
        let ary = [],
            res = this.exec(str);
        while (res) {
            //=> Store each captured content RES[0] in an array
            ary.push(res[0]);
            //=> As long as the captured content is not NULL, the capture continues
            res = this.exec(str);
        }
        return ary.length === 0 ? null : ary;
    }
    RegExp.prototype.execAll = execAll; }) ();let reg = /\d+/g;
console.log(reg.execAll('Xiao Ming 2019@2020 Take off'));
//=> The MATCH method in the string can be executed once, and all matches can be captured (if the re is also set to G).
console.log('Xiao Ming 2019@2020 Take off'.match(reg));
Copy the code

Group capture of re

//=> ID card number
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"]
//=> The first item: the result of the grand re match
//=> Remaining items: Each small group individually matches the captured results
//=> If you set grouping (change priority), but do not need to capture separately, can be based on? : to deal with
Copy the code
{0} => {0} => {0} => {0} => {0} =
let str = '{0} year {1} Month {2} day ';

Let reg = /\{(\d+)\}/; 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}"] many times match, the match can only match the big regular access to the content, information without access to a small group 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"]
Copy the code
//=> Third function of grouping: "grouping reference"
let str = 'book'; //=>"good", "look", "moon", "foot"...
let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/; //=> Group reference is to use "\ number" to make its representation and corresponding group appear exactly the same content
console.log(reg.test('book')); //=>true
console.log(reg.test('deep')); //=>true
console.log(reg.test('some')); //=>false
Copy the code

Cupidity of regular capture

let str = 'Xiao Ming 2019@2020 Take off';
Greedy for re capture: By default, the longest result matched by the current re is captured
let reg = /\d+/g;
console.log(str.match(reg)); / / = > [" 2019 ", "2020"]

//=> Set after the quantifier metacharacter? : Uncupidity of capture (obtained as the shortest result of regular matching)
reg = /\d+? /g;
console.log(str.match(reg)); //=>["2", "0", "1", "9", "2", "0", "2", "0"]
Copy the code

The five functions of question marks in re:

  • The left side of the question mark is a non-quantifier metacharacter: itself represents a quantifier metacharacter, appearing zero to once
  • To the left of the question mark is the quantifier metacharacter: ungrabbility
  • (? 🙂 matches only but does not capture
  • (? =) Forward check
  • (? !). Negative lessons

Other methods of re capture

  1. Test can also capture (meaning match)

    let str = '{0} year {1} Month {2} day ';
    let reg = /\{(\d+)\}/g;
    console.log(reg.test(str)); //=>true
    console.log(RegExp. $1);/ / = > "0"
    
    console.log(reg.test(str)); //=>true
    console.log(RegExp. $1);/ / = > "1"
    
    console.log(reg.test(str)); //=>true
    console.log(RegExp. $1);/ / = > "2"
    
    console.log(reg.test(str)); //=>false
    console.log(RegExp. $1);//=>"2" stores the result of the last capture
    
    //=>RegExp.$1~RegExp.$9: retrieves information about the first to ninth groups after the current re match
    Copy the code
  2. The method used to implement a replacement in the replace string (usually with a re)

    let str = 'xiaoming@2019|xiaoming@2020';
    // change "xiaoming" to "xiaoming"
    //1. Only one regex can be replaced at a time
    / * STR = STR. Replace (" xiaoming ", "Ming"). The replace (" xiaoming ", "Ming"); console.log(str); * /
    //2. Using regex is easier
    str = str.replace(/xiaoming/g.'Ming');
    console.log(str);
    Copy the code
    let str = 'xiaoming@2019|xiaoming@2020';
    // replace "xiaoming" with "xiaomingpeixun"
    //str=str.replace("xiaoming","xiaomingpeixun").replace("xiaoming","xiaomingpeixun");
    / / "xiaomingpeixunpeixun @ 2019 | xiaoming @ 2020" every replacement from string to find it the first position (similar to the regular captured lazy)
    
    //=> This can be implemented based on regular G
    str = str.replace(/xiaoming/g.'xiaomingpeixun');
    Copy the code

    Example: Processing the time string

    let time = '2019-08-13';
    //=> changes to "August 13, 2019"
    let reg = / ^ (\ d {4}) - (\ d {1, 2}) - $/ (\ d {1, 2});
    
    //=> This can be implemented
    Replace (reg,"$1 year $2 month $3 day "); //time = time.replace(reg,"$1 year $2 month $3 day ");
    //console.log(time); //=> August 13, 2019
    
    Replace ([reg],[function])
    //1. REG and TIME are matched, and the passed function is executed several times (and once it is matched).
    //2. Not only does REPLACE execute the method, but REPLACE also passes the argument information to the method (the same information as exec captures: the content of the large re match, the information of the small group match....)
    //3. Replace the current grand re match with whatever we return in the function
    / * time = time. Replace (reg, (big, $1, $2, $3) = > {/ / = > here at $1 to $3 is our own set of variable console log (big, $1, $2, $3); }); * /
    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 + 'years' + $2 + 'month' + $3 + 'day';
    });
    Copy the code

    Capitalize the first letter

    let str = 'Good good study, day day up! ';
    let reg = /\b([a-zA-Z])[a-zA-Z]*\b/g;
    //=> The function is executed six times, each time passing the regular match information to the function
    / / = > every ARG: [" good ", "g"] [" good ", "g"] [" study ", "s"]...
    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!"
    Copy the code

    What is the maximum number of occurrences of a character in a string?

    /*== the first type ==*/
    let str = 'xiaomingshigeguaihaizi';
    let obj = {};
    [].forEach.call(str, char= > {
        if (typeofobj[char] ! = ='undefined') {
            obj[char]++;
            return;
        }
        obj[char] = 1;
    });
    let max = 1,
        res = [];
    for (let key in obj) {
        let item = obj[key];
        item > max ? (max = item) : null;
    }
    for (let key in obj) {
        let item = obj[key];
        if(item === max) { res.push(key); }}console.log('most frequently occurring character:${res}Appeared,${max}Time `);
    
    /*== the second type ==*/
    let str = 'xiaomingshigeguaihaizi';
    str = str
        .split(' ')
        .sort((a, b) = > a.localeCompare(b))
        .join(' ');
    // console.log(str); //=>"aeefghhhiilnnoopsuuuxzz"
    let ary = str.match(/([a-zA-Z])\1+/g).sort((a, b) = > b.length - a.length);
    // console.log(ary); //=>["hhh", "uuu", "ee", "ii", "nn", "oo", "zz"]
    let max = ary[0].length,
        res = [ary[0].substr(0.1)];
    for (let i = 1; i < ary.length; i++) {
        let item = ary[i];
        if (item.length < max) {
            break;
        }
        res.push(item.substr(0.1));
    }
    console.log('most frequently occurring character:${res}Appeared,${max}Time `);
    
    /*== the third type ==*/
    let str = 'xiaomingshigeguaihaizi',
        max = 0,
        res = [],
        flag = false;
    str = str
        .split(' ')
        .sort((a, b) = > a.localeCompare(b))
        .join(' ');
    for (let i = str.length; i > 0; i--) {
        let reg = new RegExp('([a-zA-Z])\\1{' + (i - 1) + '} '.'g');
        str.replace(reg, (content, $1) = > {
            res.push($1);
            max = i;
            flag = true;
        });
        if (flag) break;
    }
    console.log('most frequently occurring character:${res}Appeared,${max}Time `);
    Copy the code

    Other methods: formatTime, queryURLParams, Cart

    ~ (function () {
        / * * formatTime: Template rules :{0}-> year {1~5}-> month/day/minute/second * @return * [string] Formatted time string * by  xiaomingpeixun on 2019/08/13 */
        function formatTime(templete = '{0} year {1} Month {2} day {3} {4} minutes {5} seconds') {
            let timeAry = this.match(/\d+/g);
            return templete.replace(/\{(\d+)\}/g.(. [, $1]) = > {
                let time = timeAry[$1] | |'00';
                return time.length < 2 ? '0' + time : time;
            });
        }
    
        / * * queryURLParams: * @params * @return * [object] Store all question marks as key-value pairs and return * by Xiaomingpeixun on 2019/08/13 */
        function queryURLParams() {
            let obj = {};
            this.replace(/([^?=&#]+)=([^?=&#]+)/g.(. [, $1, $2]) = > (obj[$1] = $2));
            this.replace(/#([^?=&#]+)/g.(. [, $1]) = > (obj['HASH'] = $1));
            return obj;
        }
    
        /* * Chromatic: Implements million-year processing of large numbers * @params * @return * [string] Million-year string * by Xiaomingpeixun on 2019/08/13 */
        function millimeter() {
            return this.replace(/ \ d {1, 3} (? =(\d{3})+$)/g.content= > content + ', ');
        }
    
        /* Extends to the built-in string.prototype class */
        ['formatTime'.'queryURLParams'.'millimeter'].forEach(item= > {
            String.prototype[item] = eval(item); }); }) ();Copy the code