# 正则表达式

正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

一个用来描述或者匹配一系列符合某个语法规则的字符串的语言。在很多文本编辑器或其他工具里,正则表达式通常被用来检索、替换或拆分那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。

# 正则的应用

  • 执行字符串函数无法完成的特殊的匹配、拆分、替换功能
  • 数据验证、文本替换、内容检索、过滤内容

# 正则(RegExp 对象)

RegExp 是正则表达式的缩写。RegExp 对象用于存储检索模式,主要应用于数据验证和数据查询两个方面。

# 创建

# 实例化 RegExp对象

var reg=new RegExp(正则表达式,模式修正符);
模式修正符 描述
i 执行对大小写不敏感的匹配。
g 执行全局匹配(查找所有匹配)
m 执行多行匹配
// 简单案例
var arr=["aa","bb","cc","dd"];
var str="aaffddxxccrbbrffdd";
function mingan(arr,str){
  arr.forEach((value,index)=>{
    var reg=new RegExp(value,"g");
    str=str.replace(reg,"**");
  })
  return str;
}
console.log(mingan(arr,str));
console.log(str);

# 通过字面量方式创建

var reg=/正则表达式/
//   //内不需要加引号

通常将正则表达式字符串放在, /RegExp/中间,/ / 称为定界符。

# RegExp的方法

  • test(字符串);
    判断字符串是否符合正则的匹配,返回值是一个Boolean值

  • exec(字符串);
    查询字符串中符合正则匹配的内容,返回值是数组。如果没有发现匹配,则返回 null。

    • 结果是数组
    • index:查询到结果的下标
    • input: 被查询到的字符串
    • 如果正则表达式没有设置g,那么exec方法不会对正则表达式有任何的影响。 如果设置了g,那么exec执行之后会更新正则表达式的lastIndex属性,表示本次匹配后,所匹配字符串的下一个字符的索引,下一次再用这个正则表达式匹配字符串的时候就会从上次的lastIndex属性开始匹配。
    var str="I love antzone ,this is animate";
    var reg=/an/g;
    console.log(reg.exec(str));
    console.log(reg.exec(str));
    console.log(reg.exec(str));
    
    // 控制台输出
    //  ["an", index: 7, input: "I love antzone ,this is animate", groups: undefined]
    //  ["an", index: 24, input: "I love antzone ,this is animate", groups: undefined]
    //  null
    
  • compile(正则表达式,[,flag]);
    用于在脚本执行过程中编译正则表达式,也可用于改变和重新编译正则表达式。

# 原子、量词、边界

原子是正则表达式中的最小的元素,包括英文、标点符号等

原子 含义
\d 表示匹配1个0-9的数字 [0-9]
\D [^0-9] 表示匹配除数字0-9以外的字符
\w 匹配数字、字母、下划线
\W 匹配除了数字、字母、下划线以外的字符
\s 匹配空格
\S 匹配非空格
. 查找单个字符,除了换行和行结束符
\n 查找换行符
\n 换行字符
\f 换页字符
\r 回车字符
\t 制表符
\v 垂直制表符
原子表 含义
[ ] 只匹配其中的一个原子
[^] 只匹配"除了"其中字符的任意一个原子
[0-9] 匹配0-9任何一个数字
[a-z] 匹配小写a-z任何一个字母
[A-Z] 匹配大写A-Z任何一个字母
量词 含义
{n} 规定前面的一个原子重复n次
{n,} 规定前面的一个原子重复n次及n次以上
{n,m} 规定前面的一个原子重复n-m次
* 前面一个原子重复0-无数次 等价于{0,}
+ 前面一个原子重复1-无数次 等价于{1,}
?=n 匹配任何其后紧接指定字符串 n 的字符串
?!n 匹配任何其后没有紧接指定字符串 n 的字符串
符号 含义
^ 从字符串开头进行匹配
$ 匹配到字符串的末尾
\b 匹配单词边界
\B 匹配非单词边界
¦(这是个管道符) 符号前后两个部分只要有一侧符合即可
分组字符 含义
(exp) 用小圆括号进行分组,如日期中年月日的分组:/(\d{5})-(\d{1,2})-(\d{1,2})/

每个分组将产生分组号,从第一个括号开始,可以使用\n的形式在正则中使用分组号, 如匹配成对出现的HTML标签,可以写成:/<(\w+)></\1>/| |(?:exp)| 匹配exp正则,但不产生分组号| |exp1(?=exp2) |前瞻断言,匹配exp1,但后面必须是exp2 如匹配名字叫xianlie,但不姓zhao的人:/zhao(?=xianlie)/ | |exp1(?!=exp2) |后瞻断言,匹配exp1,但后面不能是exp2 如匹配姓zhao,但名字不叫xianlie的人:/zhao(?!xianlie)/ |

# 贪婪模式和吝啬模式

  1. 贪婪模式:查询时,查询到的字符尽可能多 (默认)
  2. 吝啬模式:查询时,查询到的字符尽可能少
    • *? 重复任意次,但尽可能少重复
    • +? 重复1次或更多次,但尽可能少重复
    • ?? 重复0次或1次,但尽可能少重复
    • {n,m}? 重复n到m次,但尽可能少重复
    • {n,}? 重复n次以上,但尽可能少重复

# 字符串方法是用正则表达式

方法 描述
search(/正则/) 返回值为第一个与正则相匹配的字符串的位置,如果没有找到任何匹配的子串,则返回 -1。
replace(/正则/,str) 用str替换符合正则表达式的对应字符
split(/正则/,num) 将字符串已正则匹配的内容分割为数组,num参数是可选参数,表示返回的个数

# 小案例

  1. 用正则表达式验证身份证号
var reg=/^[1-9][0-9]{16}[0-9xX]$/     //正则匹配身份证号
var str="11112225478963589x";
console.log(reg.test(str))
  1. 用正则表达式验证邮箱
var reg=new RegExp(/^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/);
  1. 16进制颜色正则
var reg=/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
  1. 验证车牌号
var reg=/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/
  1. 验证中文 “\u4e00”和“\u9fa5”是unicode编码,并且正好是中文编码的开始和结束的两个值,所以这个正则表达式可以用来判断字符串中是否包含中文。
var reg = /[\u4e00-\u9fa5]{2,}/

# 正则验证表单案例

对表单进行验证是js正则最常用的地方,表单验证可以节省后台的一部分压力,提升网站的性能。主要验证有以下几个地方qq号、手机号、邮箱、姓名、密码、用户名等,通过结合onblur或者onchange事件,获取表单中的内容,对其进行正则判断,从而达到前台表单验证的效果。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>完整验证表单</title>
 <style type="text/css">
 *{margin: 0;padding: 0;list-style:none;}
 body{background:#ccc;}
 .demo{width:400px;padding:40px;background:#efefef;border:solid 1px #666;margin:100px auto 0;line-height:40px;}
 label{display:inline-block;width:20%;}
 input{width:60%;}
 </style>
</head>
<body>
<div class="demo">
 <ul>
 <li>
  <label for="iptqq">Q Q:</label>
  <input type="text" id="iptqq">
  <span></span>
 </li>
 <li>
  <label for="iptPhone">手机:</label>
  <input type="text" id="iptPhone">
  <span></span>
 </li>
 <li>
  <label for="iptEmil">邮箱:</label>
  <input type="text" id="iptEmil">
  <span></span>
 </li>
 <li>
  <label for="iptNum">密码:</label>
  <input type="password" id="iptNum">
  <span></span>
 </li>
 <li>
  <label for="iptNum2">再次密码:</label>
  <input type="password" id="iptNum2">
  <span></span>
 </li>
 <li>
  <label for="iptName">姓名:</label>
  <input type="text" id="iptName">
  <span></span>
 </li>
  <li>
  <label for="iptUser">用户名:</label>
  <input type="text" id="iptUser">
  <span></span>
 </li>
 </ul>
</div>
</body>
<script type="text/javascript">
 (function(window){
 function $(id){
  return document.getElementById(id);
 };
 // 获取对象
 var iptqq = $("iptqq"),iptPhone = $("iptPhone"),iptEmil = $("iptEmil"),iptNum = $("iptNum"),iptNum2 = $("iptNum2"),iptName = $("iptName"),iptUser= $("iptUser");
 // 正则验证表达式
 // 验证密码
 var rxNum = /^[a-zA-Z]\w{5,17}$/;
 // 验证QQ
 var rxqq = /^[1-9][0-9]{4,10}$/;
 // 验证手机
 var rxPhone = /^(13[0-9]|15[012356789]|18[0-9]|17[678]|14[57])[0-9]{8}$/;
 // 验证邮箱
 var rxEmil = /^\w+@\w+\.\w+$/;
 // 验证姓名
 var rxName = /^[\u4E00-\u9FA5]{2,}$/
  // 验证用户名
 var rxUser = /^[a-zA-Z0-9_-]{4,16}$/
 // 验证密码
 cation(iptNum,rxNum);
 // 验证QQ
 cation(iptqq,rxqq);
 // 验证手机号
 cation(iptPhone,rxPhone);
 // 验证邮箱
 cation(iptEmil,rxEmil);
 // 验证姓名
 cation(iptName,rxName);
 // 验证用户名
 cation(iptUser,rxUser);
 // 封装验证函数
 iptNum2.onblur = function(){
 	if(iptNum2.value==iptNum.value){
	 	iptNum2.nextElementSibling.innerHTML = "正确"
	   	iptNum2.nextElementSibling.style.color = "green";
	}else{
	 	iptNum2.nextElementSibling.innerHTML = "错误"
	   	iptNum2.nextElementSibling.style.color = "red";
	}
 }

 function cation(element,regExp){
  element.onblur = function(){
  var txt = this.value;
  if( regExp.test( txt ) ){
   this.nextElementSibling.innerHTML = "正确"
   this.nextElementSibling.style.color = "green";
  }else{
   this.nextElementSibling.innerHTML = "错误"
   this.nextElementSibling.style.color = "red";
  }
  }
 }
 })(window)
</script>
</html>