什么是正则表达式?

正则表达式(Regular Expression,常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。

JS正则表达式基本语法

在JS里面使用正则表达式有两种方法:

//使用RegExp对象
var patt=new RegExp(pattern,modifiers);
//或者使用直接量方法
var patt=/pattern/modifiers;

注意:当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \)。比如,以下是等价的: var re = new RegExp("\\w+"); var re = /\w+/;
modifiers(修饰符)有三种取值:

  • i (ignore)对大小写不敏感的匹配。
  • g (global)全局匹配(执行所有匹配而不是在找到第一个匹配后就停止)。
  • m (mutiple)多行匹配。

正则对象的方法

  • compile 编译正则表达式,也可用于改变和重新编译正则表达式。
  • exec 检索字符串中指定的值并返回。
  • test 检索字符串中指定的值。返回 true 或 false。
  //compile例子
  var str="woman!";
  patt=/woman/g;
  patt.compile(patt); 
  str2=str.replace(patt,"person");  //输出person
  //exec例子
  var str="Hello world!";
  var patt=/Hello/g;
  var result=patt.exec(str);    //输出hello
  //test例子
  var str="Hello world!";
  var patt=/Hello/g;
  var result=patt.test(str);   //输出true

正则表达式对象的属性

  • source返回正则表达式模式的文本的复本。只读。
var re = /[a-z]/i;  
alert(re.source);//将[a-z]字符串输出  
  • lastIndex,返回字符位置,它是被查找字符串中下一次成功匹配的开始位置,默认值是-1。 lastIndex 属性被 RegExp 对象的 exec 和 test 方法修改.并且它是可写的.
var re = /[A-Z]/;  
//exec方法执行后,修改了re的lastIndex属性,  
var str = "Hello,World!!!";  
var arr = re.exec(str);  
alert(re.lastIndex);//0,因为没有设置全局标志  
re = /[A-Z]/g;  
arr = re.exec(str);  
alert(re.lastIndex);//1  
arr = re.exec(str);  
alert(re.lastIndex);//7  
  • 1...1...9返回九个在模式匹配期间找到的、最近保存的部分。只读。
  • input ($_)返回执行规范表述查找的字符串。只读。
//input 最后用于匹配的字符串(传递给test,exec方法的字符串)  
var re = /[A-Z]/;  
var str = "Hello,World!!!";  
var arr = re.exec(str);  
alert(RegExp.input);//Hello,World!!!  
re.exec("tempstr");  
alert(RegExp.input);//仍然是Hello,World!!!,因为tempstr不匹配 
  • lastMatch ($&)返回任何正则表达式搜索过程中的最后匹配的字符。只读。
//lastMatch 最后匹配的字符  
re = /[a-z]/g;  
str = "hi";  
re.test(str);  
alert(RegExp.lastMatch);//h  
re.test(str);  
alert(RegExp["$&"]);//i  ,$&是lastMatch的短名字,但由于它不是合法变量名,所以要。。
  • lastParen ($+)如果有的话,返回任何正则表达式查找过程中最后括的子匹配。只读。
//lastParen 最后匹配的分组  
re = /[a-z](\d+)/gi;  
str = "Class1 Class2 Class3";  
re.test(str);  
alert(RegExp.lastParen);//1  
re.test(str);  
alert(RegExp["$+"]);//2  
  • leftContext ($)`返回被查找的字符串中从字符串开始位置到最后匹配之前的位置之间的字符。只读。
  • rightContext ($')返回被搜索的字符串中从最后一个匹配位置开始到字符串结尾之间的字符。只读。
//leftContext  返回被查找的字符串中从字符串开始位置到最后匹配之前的位置之间的字符  
//rigthContext 返回被搜索的字符串中从最后一个匹配位置开始到字符串结尾之间的字符  
re = /[A-Z]/g;  
str = "123ABC456";  
re.test(str);  
alert(RegExp.leftContext);//123  
alert(RegExp.rightContext);//BC456  
re.test(str);  
alert(RegExp["$`"]);//123A  
alert(RegExp["$'"]);//C456  

元字符

  • . 匹配单个字符,除了换行和行结束符。
var str="That's hot!";
var patt1=/h.t/g;
str.match(patt1)  // hat,hot
  • \w 匹配单词字符。
var str="Give 100%!"; 
var patt1=/\w/g;
str.match(patt1)  //G,i,v,e,1,0,0
  • \W 匹配不是单词的字符。
var str="Give 100%!"; 
var patt1=/\w/g;
str.match(patt1)  // ,%,!
  • \d 匹配数字。
  • \D 匹配非数字字符。
  • \s 匹配空白字符。
  • \S 匹配非空白字符。
  • \b 查找单词边界。
  • \B 查找非单词边界。
  • \0 匹配 NULL 字符。
  • \n 匹配换行符。
  • \f 匹配换页符。
  • \r 匹配回车符。
  • \t 匹配制表符。
  • \v 匹配垂直制表符。
  • \xxx 查找以八进制数 xxx 规定的字符。
  • \xdd 查找以十六进制数 dd 规定的字符。
  • \uxxxx 查找以十六进制数 xxxx 规定的 Unicode 字符。

支持正则的String方法

  • search 检索与正则表达式相匹配的值,如果没有匹配成功,则返回-1
var str="Mr. Blue has a blue house"
str.search(/blue/i);  // 4
  • match 找到一个或多个正则表达式的匹配。
var str = "The rain in SPAIN stays mainly in the plain"; 
str.match(/ain/gi);   //ain,AIN,ain,ain
  • replace 替换与正则表达式匹配的子串。
var str=Visit Microsoft; 
str.replace("Microsoft","huxinmin"); // Visit huxinmin
  • split 把字符串分割为字符串数组。
var str="How are you doing today?";
str.split(" ");  // How,are,you,doing,today?

量词

  • n+ 匹配任何含有至少一个 n 的字符串。
  • n* 匹配任何含有零个或多个 n 的字符串。
  • n? 匹配任何含有零个或一个 n 的字符串。
  • n{X}匹配含有 X 个 n 的序列的字符串。
  • n{X,}X 是一个正整数。前面的模式 n 连续出现至少 X 次时匹配。
  • n{X,Y}X 和 Y 为正整数。前面的模式 n 连续出现至少 X 次,至多 Y 次时匹配。
  • n$ 匹配任何结尾为 n 的字符串。
  • ^n 匹配任何开头为 n 的字符串。
  • ?=n 匹配任何其后紧接指定字符串 n 的字符串。
  • ?!n 匹配任何其后没有紧接指定字符串 n 的字符串。

需要转义字符

需要转义的特殊字符前面加 \

  • $匹配输入字符串的结尾位置,如果需要匹配匹配输入字符串的结尾位置,如果需要匹配本身的话,使用\$
  • ^匹配输入字符串的开始位置,匹配^本身的话,使用\^
  • * 匹配前面的子表达式的零次或者多次,匹配*本身的话,使用\*
  • +匹配子表达式的1次或者多次,匹配+本身的话,使用\+
  • . 匹配除换行符之外的任何一个字符,匹配.本身的话,使用\.
  • [匹配一个中括号开始,匹配本身的,使用\[
  • ?匹配前面的子表达式的零次或者1次,或指明一个非贪婪限定符,要匹配本身的话,使用\?
  • \匹配本身的话,请使用\\
  • {标记限定符开始的地方,要匹配{ ,请使用\{
  • |指明多项中的一个选择,可以理解含义为或的意思,匹配本身的话,使用\|

贪婪模式与非贪婪模式

他们的区别:

  • 被量词修饰的子表达式的匹配行为;
  • 贪婪模式在整个表达式匹配成功的情况下尽可能多的匹配;
  • 非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配;

一些常见的修饰贪婪模式的量词如下:
{x,y} , {x,} , ? , *, 和 +
非贪婪模式就是在如上贪婪模式后加上一个?(问号),就可以变成非贪婪模式的量词;如下:
{x,y}?,{x,}?,??,*?,和 +?

  • 贪婪模式
var str = "longen<p>我是中国人</p>yunxi<p>我是男人</p>boyboy";
// 贪婪模式 匹配所有字符
console.log(str.match(/<p>.*<\/p>/)[0]); 
// <p>我是中国人</p>yunxi<p>我是男人</p>
// 后面加问号,变成非贪婪模式
console.log(str.match(/<p>.*?<\/p>/)[0]); // <p>我是中国人</p>

第一个console.log使用的是贪婪模式,我们来理解下匹配的基本原理;
首先正则是 /<p>.*<\/p>/ 匹配;<p>匹配字符串第一个字符匹配失败,接着往下,直接匹配到<p>时候,匹配成功,接着把匹配的控制权交给.*,从匹配到的<p>位置开始匹配,一直到</p>之前,接着把控制权交给</p>,接着在当前位置下往下匹配,因此匹配到</p>,匹配成功;
由于它是贪婪模式,在匹配成功的前提下,仍然会尝试向右往下匹配,因此会匹配到两个<p>标签结束;但是非贪婪模式,也就是第二个console.log();他匹配到第一个p标签成功后,它就不会再进行匹配,因此打印的值为一个p标签的内容了;

  • 非贪婪模式
var str = "longen<p>我是中国人</p>yunxi<p>我是男人</p>boyboy<p>我是中国人2</p>yunxi<p>我是男人</p>boyboy";
// 非贪婪模式1
console.log(str.match(/<p>.*?<\/p>boyboy/)[0]); 
//<p>我是中国人</p>yunxi<p>我是男人</p>boyboy
// 贪婪模式
console.log(str.match(/<p>.*<\/p>yunxi/)[0]); 
//<p>我是中国人</p>yunxi<p>我是男人</p>boyboy<p>我是中国人2</p>yunxi

我们先看表达式1,/<p>.*?<\/p>boyboy/ 匹配str字符串,首先先匹配到p标签内容;但是由于boyboy字符串一直没有匹配到,因此会一直尝试往后匹配,直到匹配到boyboy字符串后,才匹配成功,否则匹配失败;由于它是非贪婪模式,因此这时候它不会再往下进行匹配,所以匹配就结束了;因此第一个console输出为<p>我是中国人</p>yunxi<p>我是男人</p>boyboy
我们可以再来看看贪婪模式 第二个console.log()输出的; 正则表达式 /<p>.*<\/p>yunxi/ 匹配到第一个p标签yunxi后,由于它是贪婪的,它还想接着向右继续匹配,直到匹配完成后,匹配成功,才结束,因此把所有p标签后面跟随yunxi的字符串都匹配到,返回所有之间的的字符串;

方括号

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

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

() [] {}的区别

  • ()的作用是提取匹配的字符串。表达式中有几个()就会得到几个相应的匹配字符串。比如(\s+) 表示连续空格的字符串。
  • []是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示字符文本要匹配英文字符和数字。
  • {}一般用来表示匹配的长度,比如\d{3}表示匹配三个数字,\d{1,3}表示匹配1~3个数字,\d{3,} 表示匹配3个以上数字。

常用正则表达式

  1. 用户名正则
//用户名正则,4到16位(字母,数字,下划线,减号)
var uPattern = /^[a-zA-Z0-9_-]{4,16}$/;
  1. 密码强度正则
//密码强度正则,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符
var pPattern = /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/;
  1. 整数正则
//正整数正则
var posPattern = /^\d+$/;
//负整数正则
var negPattern = /^-\d+$/;
//整数正则
var intPattern = /^-?\d+$/;
  1. 数字正则
    可以是整数也可以是浮点数
//正数正则
var posPattern = /^\d*\.?\d+$/;
//负数正则
var negPattern = /^-\d*\.?\d+$/;
//数字正则
var numPattern = /^-?\d*\.?\d+$/;
  1. Email正则
//Email正则
var ePattern = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
  1. 手机号码正则
//手机号正则
var mPattern = /^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/;
  1. 正则匹配身份证号码
//身份证号(18位)正则
var cP = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
  1. URL正则
//URL正则
var urlP= /^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
  1. IPv4地址正则
//ipv4地址正则
var ipP = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
  1. 十六进制颜色正则
//RGB Hex颜色正则
var cPattern = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
  1. 日期正则
//日期正则,简单判定,未做月份及日期的判定
var dP1 = /^\d{4}(\-)\d{1,2}\1\d{1,2}$/;
//日期正则,复杂判定
var dP2 = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/;
  1. QQ号码正则
//QQ号正则,5至11位
var qqPattern = /^[1-9][0-9]{4,10}$/;
  1. 微信号正则
//微信号正则,6至20位,以字母开头,字母,数字,减号,下划线
var wxPattern = /^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/;
  1. 车牌号正则
//车牌号正则
var cPattern = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/;
  1. 包含中文正则
//包含中文正则
var cnPattern = /[\u4E00-\u9FA5]/;