1、什么是正则表达式?

正则表达式是构成搜索模式(search pattern)的字符序列。
当您搜索文本中的数据时,您可使用搜索模式来描述您搜索的内容。
正则表达式可以是单字符,或者更复杂的模式。
正则表达式可用于执行所有类型的文本搜索和文本替换操作。

2、JavaScript RegExp 对象

RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具。

2.1、语法

直接量语法:
/pattern/attributes
创建 RegExp 对象的语法:
new RegExp(pattern, attributes);

  • 参数
    • 参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。
    • 参数 attributes 是一个可选的字符串,包含属性 “g”、”i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配。ECMAScript 标准化之前,不支持 m 属性。如果 pattern 是正则表达式,而不是字符串,则必须省略该参数。
  • 返回值
    • 一个新的 RegExp 对象,具有指定的模式和标志。如果参数 pattern 是正则表达式而不是字符串,那么 RegExp() 构造函数将用与指定的 RegExp 相同的模式和标志创建一个新的 RegExp 对象。
    • 如果不用 new 运算符,而将 RegExp() 作为函数调用,那么它的行为与用 new 运算符调用时一样,只是当 pattern 是正则表达式时,它只返回 pattern,而不再创建一个新的 RegExp 对象。
  • 抛出
    • SyntaxError - 如果 pattern 不是合法的正则表达式,或 attributes 含有 “g”、”i” 和 “m” 之外的字符,抛出该异常。
    • TypeError - 如果 pattern 是 RegExp 对象,但没有省略 attributes 参数,抛出该异常。

2.2、修饰符

修饰符 描述
i 执行对大小写不敏感的匹配。
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m 执行多行匹配。

2.3、方括号

方括号用于查找某个范围内的字符:

表达式 描述
[abc] 查找方括号之间的任何字符。
[^abc] 查找任何不在方括号之间的字符。
[0-9] 查找任何从 0 至 9 的数字。
[a-z] 查找任何从小写 a 到小写 z 的字符。
[A-Z] 查找任何从大写 A 到大写 Z 的字符。
[A-z] 查找任何从大写 A 到小写 z 的字符。
[adgk] 查找给定集合内的任何字符。
[^adgk] 查找给定集合外的任何字符。
(red|blue|green) 查找任何指定的选项。

2.3、元字符

元字符(Metacharacter)是拥有特殊含义的字符:

元字符 描述
. 查找单个字符,除了换行和行结束符。
\w 查找单词字符。
\W 查找非单词字符。
\d 查找数字。
\D 查找非数字字符。
\s 查找空白字符。
\S 查找非空白字符。
\b 匹配单词边界。
\B 匹配非单词边界。
\0 查找 NUL 字符。
\n 查找换行符。
\f 查找换页符。
\r 查找回车符。
\t 查找制表符。
\v 查找垂直制表符。
\xxx 查找以八进制数 xxx 规定的字符。
\xdd 查找以十六进制数 dd 规定的字符。
\uxxxx 查找以十六进制数 xxxx 规定的 Unicode 字符。

2.4、量词

量词 描述
n+ 匹配任何包含至少一个 n 的字符串。
n* 匹配任何包含零个或多个 n 的字符串。
n? 匹配任何包含零个或一个 n 的字符串。
n{X} 匹配包含 X 个 n 的序列的字符串。
n{X,Y} 匹配包含 X 至 Y 个 n 的序列的字符串。
n{X,} 匹配包含至少 X 个 n 的序列的字符串。
n$ 匹配任何结尾为 n 的字符串。
^n 匹配任何开头为 n 的字符串。
?=n 匹配任何其后紧接指定字符串 n 的字符串。
?!n 匹配任何其后没有紧接指定字符串 n 的字符串。

2.5、RegExp 对象属性

属性 描述 FF IE
global RegExp 对象是否具有标志 g。 1 4
ignoreCase RegExp 对象是否具有标志 i。 1 4
lastIndex 一个整数,标示开始下一次匹配的字符位置。 1 4
multiline RegExp 对象是否具有标志 m。 1 4
source 正则表达式的源文本。 1 4

2.6、RegExp 对象方法

方法 描述 FF IE
compile 编译正则表达式。 1 4
exec 检索字符串中指定的值。返回找到的值,并确定其位置。 1 4
test 检索字符串中指定的值。返回 true 或 false。 1 4

2.7、支持正则表达式的 String 对象的方法

方法 描述 FF IE
search 检索与正则表达式相匹配的值。 1 4
match 找到一个或多个正则表达式的匹配。 1 4
replace 替换与正则表达式匹配的子串。 1 4
split 把字符串分割为字符串数组。 1 4

3、代码演示

1、简单的方括号和量词使用

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>JavaScript中的正则表达式</title>
  7. </head>
  8. <body>
  9. <h1>JavaScript中的正则表达式</h1>
  10. </body>
  11. <script>
  12. //正则的使用
  13. var str = "wert45678yuiytrew";
  14. //使用正则匹配子串str中的数字
  15. console.log(str.match(/[0-9]+/));
  16. //使用RegExp创建一个正则对象
  17. var pat = new RegExp("[0-9]+");
  18. console.log(str.match(pat));
  19. console.log(pat.exec(str));
  20. //以上三个返回结果一致:["45678", index: 4, input: "wert45678yuiytrew", groups: undefined]
  21. console.log("==============================");
  22. //正则搜索
  23. console.log(str.search(/[0-9]+/)); //4 返回首次匹配位置 ,没有返回-1
  24. console.log(str.search(pat)); //4 返回首次匹配位置 ,没有返回-1
  25. console.log(pat.test(str)); //true 返回是否匹配
  26. //匹配多个
  27. console.log("==============================");
  28. var str = "wert45678yui456ytr678ew";
  29. console.log(str.match(/[0-9]+/)); //默认只匹配一次
  30. console.log(str.match(/[0-9]+/g)); //(3) ["45678", "456", "678"] 使用g修饰符 匹配所有
  31. </script>
  32. </html>

2、对象方法使用

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript中的正则表达式</title>
</head>
<body>
    <h1>JavaScript中的正则表达式</h1>
</body>
<script>
    //正则的使用
    var str = "wer245ty4d56fg78hj987k";
    //使用正则匹配子串str中的数字
    //console.log(str.match(/[0-9]/g)); //匹配任意一位数字
    //console.log(str.match(/[0-9][0-9]/g)); //匹配任意两位数字
    //console.log(str.match(/[0-9]{2}/g)); //匹配任意两位数字
    //console.log(str.match(/[0-9][0-9][0-9]/g)); //匹配任意三位数字
    //console.log(str.match(/[0-9]{3}/g)); //匹配任意三位数字
    //console.log(str.match(/[0-9]{2,3}/g)); //匹配任意两位或三位数字
    //console.log(str.match(/\d{2,3}/g)); //匹配任意两位或三位数字

    console.log(str.match(/\d+/g)); //匹配至少一位数字
    console.log(str.match(/\d{1,}/g)); //匹配至少一位数字
    console.log(str.match(/[0-9]{1,}/g)); //匹配至少一位数字

    //\d{1,}  [0-9]{1,}  \d+  [0-9]+ 都表示至少一位的数字

    //精确匹配
    var pat = new RegExp("[0-9]+");
    console.log(pat.test("er2567thj")); //true 匹配子串中是否含有数字

    var pat = new RegExp("^[0-9]+");
    console.log(pat.test("er2567thj")); //false 匹配子串中是否是以数字开头
    console.log(pat.test("2567thj"));   //true 匹配子串中是否是以数字开头

    var pat = new RegExp("[0-9]+$");
    console.log(pat.test("er2567thj")); //false 匹配子串中是否是以数字结尾
    console.log(pat.test("wer2567"));   //true 匹配子串中是否是以数字结尾

    var pat = new RegExp("^[0-9]+$");
    console.log(pat.test("2567thj"));   //false 匹配子串中是否是纯数字
    console.log(pat.test("wer2567"));   //false 匹配子串中是否是纯数字
    console.log(pat.test("2567"));   //true 匹配子串中是否是纯数字

    var pat2 = new RegExp("^[0-9]{6}$"); //精确匹配任意6位数字
</script>
</html>

3、replace和split中的正则

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript中的正则表达式</title>
</head>
<body>
    <h1>JavaScript中的正则表达式分割和替换</h1>
</body>
<script>
    var str = "23:45:67:89:87:63";
    console.log(str.split(":")); //(6) ["23", "45", "67", "89", "87", "63"] 使用子串拆分

    str = "23:45;67:89!87#63";
    console.log(str.split(/[^0-9]/)); //(6) ["23", "45", "67", "89", "87", "63"] 使用正则拆分


    str = "23:45;67:89!87#63";
    //将上面子串中的分隔符统一替换成逗号,
    console.log(str.replace(/[^0-9]/g,",")); //23,45,67,89,87,63

    str = "<b>aaa</b><b>bb>b</b><b>ccc</b>";
    //将上面子串中的<b></b>标签替换成<i></i>   下面其中$1表示重复正则中第一个小括号中内容
    console.log(str.replace(/<b>(.*?)<\/b>/g,"<i>$1</i>")); //.*是贪婪匹配(最大) .*?是拒绝贪婪匹配(最小)

    console.log("=========================================");

    str = "04/28/2020"; //西方日期格式,请使用正则替换成中国的[年-月-日]格式
    console.log(str.replace(/(\d{2})\/(\d{2})\/(\d{4})/,"$3-$1-$2"));
    //其中$1,$2 $3表示重复正则中第一、第二、第三个小括号中内容
</script>
</html>

4、简单小案例

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript中的正则表达式</title>
</head>
<body>
    <h1>JavaScript中的正则表达式在表单验证中的实例</h1>
    <form action="js03.html" name="myform" onsubmit="return doSubmit()" method="post">
        账号:<input type="text" name="uname" onblur="checkUname()" /><br/><br/>
        邮箱:<input type="text" name="email" onblur="checkEmail()"/><br/><br/>
        <input type="submit" value="提交"/>
    </form>
</body>
<script>
    //验证账号函数
    function checkUname(){
        //获取账号信息
        var uname = document.myform.uname.value;
        //执行验证
        //if(uname.match(/^[0-9A-Za-z_]{8,16}$/) == null){
        if(uname.match(/^\w{8,16}$/) == null){
            alert("请输入8~16位的账号信息!");
            return false;
        }
        return true;
    }

    //验证邮箱函数
    function checkEmail(){
        //获取账号信息
        var email = document.myform.email.value;
        //执行验证
        if(email.match(/^\w+@\w+(\.\w+){1,2}$/) == null){
            alert("请输入正确的Email信息!");
            return false;
        }
        return true;
    }

    //表单提交
    function doSubmit(){
        return checkUname() && checkEmail();
    }
</script>
</html>

4、案例练习

1、案例需求及代码:

程序猿小明需要为公司员工的个人信息录入编写前端代码,效果如下图
需求:要保证信息录入格式正确无遗漏(输入有误要给到对应提示)
image.png
案例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>信息登记</title>
    <link rel="stylesheet" href="./css/messages.css">
</head>
<body>
    <div id = "content" >
        <div id="title">个人信息登记表</div>
        <form id = "registForm" method="POST" name="myform" onsubmit="return doSubmit()">
            <div id = "layout-bg">
                <ul class="reg-list">
                    <li>
                        <div class="label">登录账号:</div>
                        <div class="r-txt"><input class = "inptxt" type="text" name="uname" onblur="checkUname()" /></div>
                        <div class="tips">6~18位有效字符(字母、数字、下划线)</div>
                    </li>
                    <li>
                        <div class="label">登录密码:</div>
                        <div class="r-txt"><input class = "inptxt" type="password" name="upass" onblur="checkUpass()" /></div>
                        <div class="tips">6~18位任意字符</div>
                    </li>
                    <li>
                        <div class="label">重复密码:</div>
                        <div class="r-txt"><input class = "inptxt" type="password" name="rpass" onblur="checkRpass()" /></div>
                        <div class="tips">重复密码与登录密码一致</div>
                    </li>
                    <li>
                        <div class="label">性&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;别:</div>
                        <div class="r-txt" id="sex">
                            <input type="radio" name="sex" value="1"/>男&nbsp;&nbsp;&nbsp;&nbsp;
                            <input type="radio" name="sex" value="0"/>女
                        </div>
                        <div class="tips">必须选择一个</div>
                    </li>
                    <li>
                        <div class="label">年&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;龄:</div>
                        <div class="r-txt"><input class = "inptxt" type="text" name="uAge" onblur="checkUAge()" /></div>
                        <div class="tips">大于0的任意两位整数</div>
                    </li>
                    <li>
                        <div class="label">手机号码:</div>
                        <div class="r-txt"><input class = "inptxt" type="text" name="uTel" onblur="checkUTel()" /></div>
                        <div class="tips">由1开头的11位整数</div>
                    </li>
                    <li>
                        <div class="label">邮&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱:</div>
                        <div class="r-txt"><input class = "inptxt" type="text" name="uEmail" onblur="checkUEmail()" /></div>
                        <div class="tips">有效的Email地址</div>
                    </li>
                    <li>
                        <div class="label">学&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;历:</div>
                        <div class="r-txt" id="edu">
                            <select name="uEducation" >
                                <option value=" " selected>请选择</option>
                                <option value="0">大专</option>
                                <option value="1">本科</option>
                                <option value="2">硕士</option>
                            </select>
                        </div>
                        <div class="tips">必须选择一个学历选项</div>
                    </li>
                    <li>
                        <div class="btn" style="margin-left: 70px;">
                            <input class="button" type="submit" value="提交"/>
                        </div>
                        <div class="btn">
                            <input class="button" type="reset" value="重置" onclick="doReset()"/>
                        </div>
                    </li>

                </ul>

            </div>
        </form>
    </div>

</body>
<script type="text/javascript" src="./js/messages.js"></script>
</html>

css:

/* 全局设置,取消默认属性 */
* {margin:0px;padding: 0px;}
li {list-style: none;}
/* content样式 */
#content{width: 980px;height: 600px;background-color: #F0F7FF;margin: 10px auto;border: 1px solid #808080;}
/* form样式 */
#registForm{display: block;}

/* title样式 */
#title{font-size: 40px;color: black;margin: 30px 65px;font-weight: bold;}
/* li */
li{display: block;}
li .label,.r-txt,.tips {display: inline-block;}
.label{margin: 10px 5px 10px 70px;width: 70px;height: 28px;}
.r-txt{width: 200px;height: 22px;}
.r-txt,.tips{margin: 10px;}
.tips{line-height: 22px;color: darkgray; font-size: 13px;}
/* input */
.inptxt{height: 18px;width:200px ;line-height: 18px;border: 1px solid #cfcdc7;background: #fff;color: #999;padding: 5px 0 5px 5px;}
/* button */
.btn{margin:10px;display: inline-block;}
.button{height: 22px;width: 40px;text-align: center;}

js:

//验证账号函数
function checkUname(){
    //获取账号信息
    var uname = document.myform.uname;
    //执行验证
    if(uname.value.match(/^\w{6,18}$/) == null){
        alert("账号请输入6~18位有效字符!");
        // console.log(uname.parentNode.nextSibling.nextSibling)
        uname.parentNode.nextSibling.nextSibling.style.color = "red";

        return false;
    }
    uname.parentNode.nextSibling.nextSibling.style.color = "darkgray";
    return true;
}

//验证密码函数
function checkUpass(){
    //获取密码信息
    var upass = document.myform.upass;
    //执行验证
    if(upass.value.match(/^.{6,18}$/) == null){
        alert("密码请输入6~18位!");
        upass.parentNode.nextSibling.nextSibling.style.color = "red";
        return false;
    }
    upass.parentNode.nextSibling.nextSibling.style.color = "darkgray";
    return true;
}

// 验证重复输入的密码函数
function checkRpass(){
    //获取密码信息
    var upass = document.myform.upass;
    //获取重复密码信息
    var rpass = document.myform.rpass;
    if (upass.value != rpass.value){
        alert("两次密码不匹配!");
        rpass.parentNode.nextSibling.nextSibling.style.color = "red";
        return false;
    }
    rpass.parentNode.nextSibling.nextSibling.style.color = "darkgray";
    return true;
}

// 验证年龄函数
function checkUAge(){
    //获取年龄信息
    var uage = document.myform.uAge;
    if (uage.value.match(/\d{2}/) == null || Number(uage) <= 0){
        alert("请输入大于0的两位整数!");
        uage.parentNode.nextSibling.nextSibling.style.color = "red";
        return false;
    }
    uage.parentNode.nextSibling.nextSibling.style.color = "darkgray";
    return true;

}

// 验证电话号码
function checkUTel(){
    //获取电话号码信息
    var utel = document.myform.uTel;
    if (utel.value.match(/^1\d{10}$/) == null){
        alert("请输入正确的手机号码!");
        utel.parentNode.nextSibling.nextSibling.style.color = "red";
        return false;
    }
    utel.parentNode.nextSibling.nextSibling.style.color = "darkgray";
    return true;
}


//验证邮箱函数
function checkUEmail(){
    //获取账号信息
    var email = document.myform.uEmail;
    //执行验证
    if(email.value.match(/^\w+@\w+(\.\w+){1,2}$/) == null){
        alert("请输入有效的Email信息!");
        email.parentNode.nextSibling.nextSibling.style.color = "red";
        return false;
    }
    email.parentNode.nextSibling.nextSibling.style.color = "darkgray";
    return true;
}

// 检查是否选择了性别
function checkSex(){
    //获取性别信息
    var sex = document.myform.sex;
    if (sex.value == ""){
        alert("请选择您的性别!");
        document.getElementById("sex").nextElementSibling.style.color = "red";
        return false;
    }
    document.getElementById("sex").nextElementSibling.style.color = "darkgray";
    return true;
}

// 检查是否选择了学历
function checkEducation(){
    //获取学历信息
    var education = document.myform.uEducation;
    if (education.value == " "){
        alert("请选择您的学历!");
        document.getElementById("edu").nextElementSibling.style.color = "red";
        return false;
    }
    document.getElementById("edu").nextElementSibling.style.color = "darkgray";
    return true;
}

//表单提交
function doSubmit(){
    return checkUname() && checkUpass() && checkRpass() && checkUAge() && checkUTel() && checkUEmail() && checkSex() && checkEducation();
}

// 重置的时候,把所有的文字颜色改为原样
function doReset(){
    var tlist = document.getElementsByClassName("tips");
    // console.log(tlist);
    for (var i = 0; i < tlist.length; i++){
        // console.log(i);
        tlist[i].style.color = "darkgray";
    }
}

运行截图:
image.png

2、遇到的问题:

1、切记要带px,px,px!重要的事情说三遍!!!
2、单选框radio不选的时候值为””,而不是null。
3、画盒子画盒子画盒子!
4、选择同级元素nextSibling可能需要两次,但是nextElementSibling一次就可以拿到,然后radio的input框为啥我的找不到父元素,只好加了个id来获取盒子。