天天看點

JavaScript全解析——正規表達式

作者:陸榮濤

正則——RegExp

●正則也叫正規表達式,又名 “規則表達式”

●正則是JS中的資料類型, 是一個複雜資料類型

●由我們自己來書寫 “規則”,專門用來檢測 字元串 是否符合 “規則” 使用的

●我們使用一些特殊的字元或者符号定義一個 “規則公式”,然後用我們定義好的 “規則公式” 去檢測字元串是不是合格

var reg = /\d+/
var str1 = '123'
var str2 = 'abc'
console.log(reg.test(str1)) // true
console.log(reg.test(str2)) // false           

●上面的變量 reg 就是定制好的規則

●檢測 str1 這個字元串的時候,符合規則

●檢測 str2 這個字元串的時候,不符合規則

建立一個正規表達式

●想制定 “規則”,必須要按照人家要求的方式來制定

●把一些字母和符号寫在 // 中間的東西,叫做正規表達式,比如 /abcdefg/

●建立正規表達式有兩個方式 字面量 和 構造函數建立

字面量建立

// 下面就是字面量建立一個正規表達式
var reg = /abcdefg/           

●這個正規表達式就可以去檢測字元串了

●這個正規表達式的意義是字元串中的必須要包含'abcdefg'這個片段

構造函數建立

// 下面就是構造函數建立一個正規表達式
var reg = new RegExp('abcdefg')
console.log(reg) //  /abcdefg/           

●使用構造函數方式建立的和字面量建立的,得到的結果一樣

兩種建立方式的差別

●文法不一樣

●書寫辨別符的時候

○字面量方式直接書寫在正則的後面

○内置構造函數, 以第二個參數的方式傳遞

●拼接字元串

○字面量方式不接受拼接字元串

○内置構造函數方式, 可以拼接字元串

●基本元字元書寫

○字面量方式的時候, 直接書寫 \s\d\w

○内置構造函數書寫的時候, 需要書寫 \s\d\w

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //書寫辨別符的差別
        var reg = /abcd/gi
        console.log(reg)
        var reg2 = new RegExp('abcd', 'gi')
        console.log(reg2)


        // 拼接字元串的差別
        var s = 'HH'
        var s2 = 'MM'
        // 不能解析變量
        var reg = /(s|s2)/ //會報錯 不能解析變量
        // var reg = /(HH|MM)/
        console.log(reg)
        // 因為第一個參數就是需要你以 字元串 的形式傳遞 是以可以拼接字元串
        var reg2 = new RegExp('(' + s + '|' + s2 + ')')
        console.log(reg2)


        // 基本元字元的書寫的差別
        var reg = /\s\d\w/
        console.log(reg)

        var reg2 = new RegExp('\\s\\d\\w')
        console.log(reg2)
    </script>
</body>

</html>           

正規表達式的方法

●正則提供了一些方法給我們使用

●用來檢測和捕獲字元串中的内容的

test()方法——比對

●作用:test方法是用來檢測字元串是否符合我們正則的标準

●文法: 正則.test(字元串)

●傳回值: boolean

○如果該字元串符合正則的規則, 那麼就是 true

○如果該字元串不符合正則的規則, 那麼就是 false

console.log(/\d+/.test('123')) // true
console.log(/\d+/.test('abc')) // false           

exec()方法——捕獲

●作用:exec方法是把字元串中滿足條件的内容捕獲出來

●文法: 正則.exec(字元串)

●傳回值: 把字元串中符合正則要求的第一項以及一些其他資訊,以數組的形式傳回

○原始字元串中沒有符合正則要求的字元串片段

■null

○原始字元串中有符合正則要求的片段

■正則沒有 () 也沒有 全局辨別符g

●傳回值是一個數組

●索引 0 是從字元串中捕獲出來的滿足正則條件的第一個内容

●注意: 不管捕獲多少次, 每次都是從原始字元串的索引 0 開始檢索

■正則有全局辨別符 g

●傳回值是一個數組

●索引 0 是從字元串中捕獲出來的滿足正則條件的第一個内容

●注意: 第二次捕獲是從第一次的結束位置開始向後查詢, 直到最後捕獲不到為止, 再下一次的時候, 又從字元串的 索引0 開始檢索

■有 ()

●傳回的是一個數組

●索引 0 是從字元串中捕獲出來的滿足正則條件的第一個内容

●從索引 1 開始, 依次是每一個小括号的單獨内容

●注意: 按照小括号的開始标志, 來數是第幾個小括号

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //1. 沒有符合要求的片段
        var str = 'vgfdrtyuijkhvgfrtyu'
        var reg = /\d{3}/
        var res = reg.exec(str)
        console.log(res)


        //2. 有符合要求的片段
       //2-1. 沒有 () 沒有 g
        var str = 'tfyu123gvh456gfh789gyhj'
        var reg = /\d{3}/
        var res = reg.exec(str)
        console.log(res)

        //2-2. 有全局辨別符 g
        var str = 'tfyu123gvh456gfh789gyhj'
        var reg = /\d{3}/g
        var res = reg.exec(str)
        console.log(res)
        console.log(reg.exec(str))
        console.log(reg.exec(str))
        console.log(reg.exec(str))
        console.log(reg.exec(str))

        //2-3. 有 ()
        var str = '11010820030223001x'
        var reg = /(\d{2})(\d{2})(\d{2})((\d{4})(\d{2})(\d{2}))\d{2}(\d)(?:\d|x)/
        var res = reg.exec(str)
        console.log(res)
    </script>
</body>

</html>           

●擴充: () 有兩個意義

○一個整體

○單獨捕獲

○如果你想隻使用一個意義, 整體的所用, 不想在捕獲的時候單獨捕獲出來

○你可以寫成 (?:)表示比對但不捕獲

// 單獨捕獲
var reg = /(\d{2})(\d{2})(\d{2})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|x)/
var res = reg.exec('13072220041010301x')
console.log(res);           

正規表達式裡面的符号

●知道了怎麼建立一個正規表達式以後,我們就來詳細的說一下正規表達式裡面涉及到的一些符号了

元字元

基本元字元

●. : 比對非換行的任意字元 表示字元串中至少要有一個非換行的内容

●\ : 轉譯符号,把有意義的 符号 轉換成沒有意義的 字元,把沒有意義的 字元 轉換成有意義的 符号

●\s : 比對空白字元(空格/縮進/制表符/...)表示字元串中至少包含一位 空白 内容

●\S : 比對非空白字元

●\d : 比對數字 表示字元串中至少包含一位 數字(0-9)

●\D : 比對非數字 表示字元串中至少包含一位 非數字 内容

●\w : 比對數字字母下劃線 表示 一位 數字(0-9)字母(a-zA-Z)下劃線(_) 中的任意一個

●\W : 比對非數字字母下劃線 表示 一位 非數字字母下劃線 中的任意一個

●有了元字元我們就可以簡單的制定一些規則了

// 基本元字元
// \d
// 表示驗證的字元串内必須包含一位數字
var reg = /\d/
console.log(reg.test('sfdgdfgfdhfgh'));
console.log(reg.test('sfdgdfgfg4dhfgh7'));
console.log(reg.test('123sfdgdfgfg4dhfgh7'));
// \D
// 表示驗證的字元串中必須包含一位非數字
var reg = /\D/
console.log(reg.test('45613165465'));
console.log(reg.test('45613 165465'));
console.log(reg.test('45613d165465'));
console.log(reg.test('45613%165465'));
// \s
// 表示驗證的字元串中必須要包含一位空白内容
var reg = /\s/
console.log(reg.test('sgsdfhfgh'));
console.log(reg.test('sgsdf hfgh'));
console.log(reg.test('sgsdf     hfgh'));
console.log(reg.test(`sdgs
dfg`));
// \S
// 表示驗證的字元串中必須要包含一位非空白内容
var reg = /\S/
console.log(reg.test('             '));
console.log(reg.test('      d       '));
console.log(reg.test('      #       '));
console.log(reg.test('      .       '));
// \w
// 表示驗證的字元船串中必須要包含一位數字字母和下劃線
var reg = /\w/
console.log(reg.test('@#%#$%&^*&(*'));
console.log(reg.test('@#%#$%&^2*&(*'));
console.log(reg.test('@#%#$%&^b*&(*'));
console.log(reg.test('@#%#$%&^_*&(*'));
// \W
// 表示驗證的字元串中必須要包含一位非數字字母和下劃線
var reg = /\W/
console.log(reg.test('asgd353454__'));
console.log(reg.test('asgd353 454__'));
console.log(reg.test('asgd353$454__'));
// .
// 表示驗證的字元串中必須要包含一位非換行以外的内容
var reg = /./
console.log(reg.test('\n'));
console.log(reg.test('\ns'));
console.log(reg.test('\n '));
console.log(reg.test('\n@'));
// \
// 表示把有意義的點轉成了沒有意義的點
var reg = /\d\.\d/
console.log(reg.test('1.5'));
console.log(reg.test('1#5'));           

限定符

注意: 一個限定符隻能修飾符号前面的一個内容的出現次數

●* : 前一個内容重複至少 0 次,也就是可以出現 0 ~ 正無窮 次

●+ : 前一個内容重複至少 1 次,也就是可以出現 1 ~ 正無窮 次

●? : 前一個内容重複 0 或者 1 次,也就是可以出現 0 ~ 1 次

●{n} : 前一個内容重複 n 次,也就是必須出現 n 次

●{n,} : 前一個内容至少出現 n 次,也就是出現 n ~ 正無窮 次

●{n,m} : 前一個内容至少出現 n 次至多出現 m 次,也就是出現 n ~ m 次

●限定符是配合元字元使用的

// 下面正則表示驗證數字出現 0 ~ 正無窮次都可以
var reg = /\d*/
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
console.log(reg.test(str)) // true
console.log(reg.test(str2)) // true
console.log(reg.test(str3)) // true

// 下面正則表示驗證數字出現 1 ~ 正無窮次都可以
var reg = /\d+/
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
console.log(reg.test(str)) // false
console.log(reg.test(str2)) // true
console.log(reg.test(str3)) // true

// 下面正則表示驗證數字出現 0 ~ 1 次都可以
var reg = /\d?/
var str = 'abc'
var str2 = 'abc1'
console.log(reg.test(str)) // true
console.log(reg.test(str2)) // true

// 下面正則表示驗證數字必須出現 3 次
var reg = /\d{3}/
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
console.log(reg.test(str)) // false
console.log(reg.test(str2)) // false
console.log(reg.test(str3)) // true

// 下面正則表示驗證數字出現 3 ~ 正無窮次
var reg = /\d{3,}/
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
var str4 = 'abcd1234567'
console.log(reg.test(str)) // false
console.log(reg.test(str2)) // false
console.log(reg.test(str3)) // true
console.log(reg.test(str4)) // true

// 下面正則表示驗證數字隻能出現 3 ~ 5 次
var reg = /\d{3,5}/
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
var str4 = 'abc12345'
console.log(reg.test(str)) // false
console.log(reg.test(str2)) // false
console.log(reg.test(str3)) // true
console.log(reg.test(str4)) // true           

邊界符

●^ : 表示開頭

●$ : 表示結尾

●邊界符是限定字元串的開始和結束的

// 下面表示從開頭到結尾隻能有數字,并且出現 3 ~ 5 次
var reg = /^\d{3,5}$/
var str = 'abc'
var str2 = 'abc123'
var str3 = '1'
var str4 = '1234567'
var str5 = '123'
var str6 = '12345'
console.log(reg.test(str)) // false
console.log(reg.test(str2)) // false
console.log(reg.test(str3)) // false
console.log(reg.test(str4)) // false
console.log(reg.test(str5)) // true
console.log(reg.test(str6)) // true           

特殊符号

●() : 限定一組元素

●[] : 字元集合,表示寫在 [] 裡面的任意一個都行

●[^] : 反字元集合,表示寫在 [^] 裡面之外的任意一個都行

●- : 範圍,比如 a-z 表示從字母 a 到字母 z 都可以

●| : 或,正則裡面的或 a|b 表示字母 a 或者 b 都可以

●現在我們就可以把若幹符号組合在一起使用了

// ()
    var reg = /^(abc){2}$/
    console.log(reg.test('abcabc'));
    console.log(reg.test('aabbcc'));
    console.log(reg.test('abcc'));

    // |
    var reg = /^abc|def$/
    console.log(reg.test('abcabc'));
    console.log(reg.test('abc'));
    console.log(reg.test('def'));
    console.log(reg.test('abcdef'));
    console.log(reg.test('defdef'));
    console.log(reg.test('sddhdggfhdgsf'));

    var reg = /^(abc|def)$/
    console.log(reg.test('abcabc'));
    console.log(reg.test('abcdef'));
    console.log(reg.test('defdef'));
    console.log(reg.test('abcsddhdggfhdgsf'));
    console.log(reg.test('sddhdggfhdgsdef'));
    console.log(reg.test('abc'));
    console.log(reg.test('def'));

    // []
    var reg = /^[abcd]$/
    console.log(reg.test('a'));
    console.log(reg.test('b'));
    console.log(reg.test('c'));
    console.log(reg.test('d'));
    console.log(reg.test('e'));

    // [^]

    var reg = /^[^abcd]$/
    console.log(reg.test('a'));
    console.log(reg.test('b'));
    console.log(reg.test('c'));
    console.log(reg.test('d'));
    console.log(reg.test('e'));

    // -
    var reg = /^[0-9]$/
    console.log(reg.test('01'));
    console.log(reg.test('1'));
    console.log(reg.test('2'));
    console.log(reg.test('3'));
    console.log(reg.test('4'));
    console.log(reg.test('5'));
    console.log(reg.test('6'));
    console.log(reg.test('7'));
    console.log(reg.test('8'));
    console.log(reg.test('9'));           

辨別符(修飾符)

●書寫在正規表達式的外面, 專門用來修飾整個正規表達式的符号

●i :ignore的簡寫 表示忽略大小寫

○這個 i 是寫在正則的最後面的

○/\w/i

○就是在正則比對的時候不去區分大小寫

●g : global的簡寫 表示全局比對

○這個 g 是寫在正則的最後面的

○/\w/g

○就是全局比對字母數字下劃線

var reg = /^[a-z]$/i
console.log(reg.test('s'));
console.log(reg.test('g'));
console.log(reg.test('y'));
console.log(reg.test('u'));
console.log(reg.test('A'));

// 有全局修飾符 g
var str = 'sda123fdhm456fnbvb789gdghj345khmgn666bxcvxb'
var reg = /\d{3}/g
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));           

字元串和正則合用的方法

●字元串中有一些方法也是可以和正則一起使用的

search

●作用:search 是查找字元串中是否有滿足正則條件的内容

●文法:

○字元串.search(正則)

○字元串.search(字元串片段)

●傳回值 : 有的話傳回開始索引,沒有傳回 -1

var reg = /\d{3}/
var str = 'hello123'
var str2 = 'hello'
console.log(str.search(reg)) // 5
console.log(str2.search(reg)) // -1           

match

●作用:match 找到字元串中符合正則條件的内容傳回

●文法:

○字元串.match(正則)

○字元串.match(字元串片段)

●傳回值 :

○沒有标示符 g 的時候,是和 exec 方法一樣

○有标示符 g 的時候,是傳回一個數組,裡面是比對到的每一項

var reg = /\d{3}/
var str = 'hello123world456'
var str2 = 'hello'
console.log(str.match(reg))
// ["123", index: 5, input: "hello123wor456", groups: undefined]
console.log(str2.match(reg)) // null


var reg = /\d{3}/g
var str = 'hello123world456'
var str2 = 'hello'
console.log(str.match(reg))
// ["123", "456"]
console.log(str2.match(reg)) // null           

replace

●作用:replace 是将字元串中滿足正則條件的字元串替換掉

●文法:

○字元串.replace('換下字元', '換上字元')

○字元串.replace(正規表達式, '換上字元')

●傳回值 : 替換後的字元串

○當你的第一個參數傳遞字元串的時候, 隻能替換一個

○當你的第一個參數傳遞正規表達式的時候, 隻能替換一個

○但是如果你的正規表達式有全局辨別符 g, 那麼有多少替換多少

<script>
    var str = 'fctyHHguHHijHHknHHjgHHhfMMctMMdrMMf'
    console.log(str) //fctyHHguHHijHHknHHjgHHhfMMctMMdrMMf

    var r1 = str.replace('HH', '**')
    console.log(r1) //fcty**guHHijHHknHHjgHHhfMMctMMdrMMf

    var r2 = str.replace(/HH/, '**')
    console.log(r2) //fcty**guHHijHHknHHjgHHhfMMctMMdrMMf

    var r3 = str.replace(/HH/g, '**')
    console.log(r3) //fcty**gu**ij**kn**jg**hfMMctMMdrMMf
</script>           

案例——密碼強度校驗

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        div {
            width: 300px;
            height: 200px;
            border: 10px solid pink;
            margin: 20px auto;
            padding: 20px;
        }

        input {
            width: 100%;
            height: 50px;
            font-size: 24px;
            padding-left: 20px;
            box-sizing: border-box;
        }

        p {
            width: 100%;
            height: 30px;
            display: flex;
            justify-content: space-between;
            margin-top: 20px;
        }

        p>span {
            width: 30%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #ccc;
            color: #fff;
            font-size: 24px;
        }

        p>span:nth-child(1).active {
            background-color: red;
        }

        p>span:nth-child(2).active {
            background-color: orange;
        }

        p>span:nth-child(3).active {
            background-color: green;
        }
    </style>
</head>

<body>

    <div>
        <input type="text">
        <p>
            <span>弱</span>
            <span>中</span>
            <span>強</span>
        </p>
    </div>

    <script>

        // 密碼強度校驗
        // + 規則:
        //   => 密碼的規則: 數字 字母 符号(@#%&)
        //   => 強度的規則:
        //     -> 弱: 有一類
        //     -> 中: 有兩類
        //     -> 強: 全包含

        // 擷取元素
        var inp = document.querySelector('input')
        var spans = document.querySelectorAll('span')

        // 準備正則
        // 隻要包含一位數字就可以
        var r1 = /\d/
            // 隻要包含一位字母就可以
        var r2 = /[a-z]/i
            // 隻要包含一位符号就可以
        var r3 = /[@#%&]/

        // 1. 給 inp 綁定 input 事件
        // 随着輸入或者删除内容實時觸發
        inp.oninput = function() {
            // 2. 拿到 inp 内輸入的内容
            var text = inp.value

            // 3. 準備一個表示級别的變量, 預設是 0
            var level = 0

            // 3-1. 依次使用正則校驗
            if (r1.test(text)) level++
            if (r2.test(text)) level++
            if (r3.test(text)) level++

             // 在每一次添加類型之前, 給所有 span 清除掉類名
            for (var i = 0; i < spans.length; i++) {
                spans[i].classList.remove('active')
                if (i < level) spans[i].classList.add('active')
            }

        }
    </script>
</body>

</html>           

案例——表單驗證

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        form {
            width: 400px;
            border: 10px solid pink;
            padding: 20px;
        }

        label {
            display: block;
            height: 80px;
            position: relative;
        }

        input {
            height: 30px;
            font-size: 24px;
            padding-left: 20px;
        }

        label>span {
            position: absolute;
            left: 0;
            top: 35px;
            font-size: 20px;
            color: red;
            display: none;
        }
    </style>
</head>

<body>

    <form>
        <label>
            使用者名: <input class="username" type="text">
            <span>請按照規則填寫使用者名</span>
        </label>
        <label>
            密碼: <input class="password" type="text">
            <span>請按照規則填寫密碼</span>
        </label>
        <label>
            手機号: <input class="phone" type="text">
            <span>請按照規則填寫手機号</span>
        </label>
        <label>
            郵箱: <input class="email" type="text">
            <span>請按照規則填寫郵箱</span>
        </label>
        <input type="button" value="完善資料">
    </form>

    <script>
        // 方案2: 統一驗證
        // 1. 給每一個 input 起一個單獨的類名(或者辨別, 用來區分)
        // 2. 準備正則, 以對象的形式準備正則, 對象的 鍵就使用 文本框的獨立辨別, 值就使用 正則
        // 當你的文本框 className === 'username' 的時候, 就使用 regObj 内的一個叫做 username 對應的正則去驗證
        var regObj = {
            username: /^[0-9a-z]\w{5,11}$/i,
            password: /^\w{6,12}$/,
            phone: /^\d{11}$/,
            email: /^[0-9a-zA-Z]\w{5,11}@(qq|163|sina)\.(com|cn)$/
        }

        // 3. 擷取到所有的文本框
        var inps = document.querySelectorAll('form input')
            // 3-2. 給每一個 input 綁定 表單輸入 事件
        inps.forEach(function(item) {
            item.oninput = function() {
                // 4-1. 拿到你正在輸入的這個 input 文本框内的文本
                var text = item.value
                    // 4-2. 拿到驗證該文本框需要使用的正則
                var reg = regObj[item.className]
                    // 4-3. 拿到應該顯示的那個對應的 span 标簽
                var span = item.nextElementSibling

                // 4-4. 操作顯示和隐藏
                span.style.display = reg.test(text) ? 'none' : 'block'
                    // if (reg.test(text)) {
                    //   span.style.display = 'none'
                    // } else {
                    //   span.style.display = 'block'
                    // }
            }
        })
    </script>
</body>

</html>           

正則預查(擴充)

正向預查

●正向肯定預查:(?=)

●正向否定預查:(?!)

負向預查

●負向肯定預查:(?<=)

●負向否定預查:(?<!)

var str = 'windows2012windows2000windowsXPwindowsVistawindows98windows'
// 1. 正向肯定預查
// 需求: 我需要的是 windows, 但是是後面帶有數字的 widnows
// var reg = /windows(?=\d+)/g
// 2. 正向否定預查
// 需求: 我需要的是 windows, 但是後面不是數字的 windows
// var reg = /windows(?!\d+)/g
// 3. 負向肯定預查
// 需求: 我需要的是 windows, 但是前面是數字的 windows
var reg = /(?<=\d+)windows/g
// 4. 負向否定預查
// 需求: 我需要的是 windows, 但是前面不是數字的 windows
var reg = /(?<!\d+)windows/g           

繼續閱讀