正则表达式详解;使用少量的代码完成复杂的操作,正则就是这么神奇

本文中所有示例采用javascript语言编写;
其中变量str一般表示字符串,reo一般表示正则对象,result 一般表示执行结果。
部分示例逻辑并不严谨,仅作为功能演示用;如果需要使用到项目中请自行完善。

是骡子是马

正则表达式可以使用简单的代码完成比较复杂的功能;以下三个示例中间分别使用正则表达式对数据进行提取、验证、替换操作,让你近距离感受正则的魅力所在。

  • 正则表达式可以很方便的在字符串中提取我们想要的信息。
    示例:
    提取字符串str中的所有电话号码。

    var str = "张三13612345678,李四18712345678,王五13312345678";
    var reo = /\d{11}/g; //规则:匹配数字(11位),全局匹配,
    var result = str.match(reo); //字符串的match()方法
    alert(result) //提示:13612345678,18712345678,13312345678
    
  • 正则表达式可以对字符串进行格式验证。
    示例:
    用户注册的时候,要求输入的用户名可以包含字符、数字、下划线,并设最小长度为6,最大长度为20。

    var reo= /^\w{6,20}/; //规则:只能已非特殊符号开头,非特殊符号长度6到20位。
    alert(reo.test("abc"))  //false(长度不够)
    alert(reo.test("#abcdef"))  //false (有特殊符号)
    alert(reo.test("abcdef_2132"))  //true	(验证通过)
    
  • 正则表达式可以快速替换字符串中符合规则的内容。
    示例:
    将字符串str中的手机号码进行脱敏处理,及隐藏中间四位数。

    var str = "张三13612345678,李四18712345678,王五13312345678";
    var reo = /(\d{3})\d{4}(\d{4})/g; //规则:组1,匹配前三位数;组2匹配后四位数
    var result = str.replace(reo, '$1****$2');//替换组1和组2中间的四位数为****
    alert(result) //提示:张三136****5678,李四187****5678,王五133****5678
    

正则简介


正则表达式(Regular Expression 或 Regex )
正则表达式,又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
通俗的讲:就是使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。

出现得早
正则表达式的"祖先"可以一直上溯至对人类神经系统如何工作的早期研究。最早可以追溯到1956年一位数学家发表的论文中引入此概念。

在线测试

使用场景

  • 批量提取/替换有规律的字符串
  • 用户录入数据的合法性验证
  • 模板引擎的标签库开发
  • 网络爬虫的数据提取开发
  • 批量文本高效处理等

应用广泛

正则表达式可以在多种文本编辑器/办公软件/开发语言中使用。

正则表达式是编程人员的必备技能!

主要功能


验证

在做表单数据提交前,我们通常会对用户录入的数据进行基础的格式验证。
比如:

  • 只能录入字母或数字(用户名)
  • 手机号码验证(用户联系电话)
  • 整数验证 (商品数量)
  • 身份证号码验证
  • 密码强度验证
  • 涉黄词语验证

查找

从大量信息中快速提取指定的内容。
比如:

  • 从一个txt小说中提取所用的章节标题
  • 从一个文章中提取所有的话号码

替换

将指定格式的文本进行正则匹配查找,找到之后进行特定替换。
比如:

  • 修改html标签名。
  • 对隐私内容进行脱敏操作。

学习正则


正则相关方法

在了解正则表达式怎么写之前,先了解一下正则相关的有哪些常用方法。

正则对象方法

正则表达式对象自带exec()和test()两个方法。

exec(str) 检索

检索指定字符串str中第一个符合的值,没有则返回null。

示例:获取字符串str中的第一个数字。

var str = "a9b2c3";
var reo = /\d/; //表达式,匹配数字
alert(reo.exec(str)) //提示:9

test(str) 验证

检测字符串str是否匹配某个规则,返回true/false。
常用对用户录入的内容进行合法性校验。

示例:判断字符串str内容是否为数字。

var str = "a1b2c3";
var reo = /^\d/; //表达式,匹配数字
alert(reo.test(str)) //提示:false
var str = "123";
alert(reo.test(str)) //提示:true

lastIndex 属性

正则开始匹配的起始位置索引。

首先看一个示例,每次test()的结果都不同。

var str = "a1bc";
var reo = /\d/g; //表达式,匹配数字
alert(reo.test(str)) //提示:true
alert(reo.test(str)) //提示:false
alert(reo.test(str)) //提示:true

这是因为每次匹配后,会把lastIndex的索引位置加1,没有匹配到时重置为0。

我们每次验证前手动重置一下即可解决。

var str = "a1bc";
var reo = /\d/g; //表达式,匹配数字

alert(reo.test(str)) //提示:true
reo.lastIndex = 0;
alert(reo.test(str)) //提示:true
reo.lastIndex = 0;
alert(reo.test(str)) //提示:true

全局模式下的exec()可以循环执行匹配所用内容就是使用的lastIndex属性实现的。

var str = "a9b2c3";
var reo = /\d/g; //表达式,匹配数字
var one;
while((one = reo.exec(str))!=null){
    
    
	alert(one); //依次提示:9;2;3
}

lastIndex 仅对正则对象自带方法有效,对字符串对象的方法是不起作用的!

字符串对象方法

search(reo) 查找

查找字符串中指定规则reo第一次出现的位置,返回位置编码或-1。

示例:获取字符串str中第一个数字出现的位置编码。

var str = "a0b2c3";
var reo = /\d/; //表达式,匹配数字
var ls = str.search(reo); //字符串的search()方法
alert(ls) //提示:1

replace(reo,xxx) 替换

j将字符串中符合指定规则reo的内容替换为xxx,返回替换后的字符串。

示例:将字符串str中的数字替换为逗号。

var str = "a1b2c3";
var reo = /\d/g; //表达式,匹配数字,全局匹配
var ls = str.replace(reo,','); //replace()方法
alert(ls) //提示:a,b,c,

split(reo) 分割

将字符串根据指定规则reo进行分割,返回分割后的数组。

示例:将字符串str根据数字分割。

var str = "a1b2c3";
var reo = /\d/; //表达式,匹配数字
var ls = str.split(reo); //字符串的split()方法
alert(ls) //提示:a,b,c,

match() 匹配

检索字符串中符合指定规则reo的值,没有全局标识时返回第一个值,有全局标识时返回匹配值的数组。

示例:1.获取字符串str中第一个数字;2.获取字符串str中的所有数字。

var str = "a1b2c3";
var reo = /\d/; //表达式,匹配数字
var ls = str.match(reo); //字符串的match()方法
alert(ls) //提示:1

reo = /\d/g; //表达式,匹配数字,全局匹配
ls = str.match(reo); //字符串的match()方法
alert(ls) //提示:1,2,3

表达式的构成

一个复杂的正则规则主要由元字符限定符修饰符普通字符组成而成。

元字符

元字符是正则表达式的基础,就好比英语中的字母ABC。
后面用到的正则表达式都依赖于元字符,组合各个元字符和字符串即可完成复杂的正则匹配。

  • 基础元字符
符号 含义 说明
. 除换行符以外的任意字符 \n以外的字符
\w 字母或数字或下划线 非特殊符号
\s 空白符 空格或tab键
\d 数字 0到9
\b 单词的开头或结尾 前后非字母取中间
^ 开头 指定前缀,在[]使用表示取反
$ 结尾 指定后缀
() 分组 或提升优先级
[] 集合 括起来内容全视为普通字符
  • 运算元字符
符号 含义 说明
^ 取反
| 或者
  • 反义元字符(大写)
符号 含义 说明
\W 匹配特殊符号 及非字母或数字或下划线的其他符号
\S 匹配非空白符
\D 匹配非数字的字符
\B 匹配单词开头或结束的位置

限定符

也可叫做重复模式,用于标记指定规则的重复次数(长度)。

符号 含义 说明
? 0/1 次 可有可无
* >=0 次 等价于 {0,}
+ >=1 次 等价于 {1,}
{n} n 次
{n,m} n-m 次
{n,} >=n 次

? 详解

表示指定规则重复匹配0次或1次,当指定内容可有可无时使用。

示例:
普通的1开头的11位数字或使用‘+86’做前缀加1开头的11位数字,我们都认为是正确手机号码格式。

var str ="13612345678";
var reo = /^1\d{10}/; //规则:普通11位的手机号码
alert(reo.test(str)) //提示:true

/*
* 规则:普通11位的手机号码,且可以带有中国地区标识(+86)
* 因为‘+86’是一个整体,需要使用括号括起来
* 然后在括号后面使用‘?’来标记‘+86’可有可无
*/
reo = /^(\+86)?1\d{10}/; 
alert(reo.test(true)) //提示:true
str ="+8613612345678";
alert(reo.test(true)) //提示:true

* 详解

当指定内容的重复规则完全不清楚时使用。

示例:
提取指定字符串str内容中,姓名‘张’什么‘峰’的。

var str ="班上有叫张三峰的、张雪峰的,还有叫张喇嘛峰的";
var reo = /张[\u4e00-\u9fa5]*峰/g; //规则:
var result = str.match(reo); //字符串的match()方法
alert(result) //提示:张三峰,张雪峰,张喇嘛峰

+ 详解

标识指定内容重复出现1次及以上。

示例:
获取指定字符串str中的所有英文单词。

var str ="hello world!";
var reo = /\b[a-zA-Z]+\b/; //规则:英文字母出现一次及以上
var result = str.match(reo); 
alert(result) //提示:hello,world

{} 详解

动态指定具体的重复规则,可以指定最小和最大值。

示例:
判断用户姓名只接受2到10位。

var str="张三丰";
var reo = /[\u4e00-\u9fa5]{2,10}/; //规则:中文,长度为2到10位
alert(reo.test(str));//提示:true
str = "丰";
alert(reo.test(str));//提示:false

贪婪与懒惰匹配

使用限定符匹配时,会有贪婪和懒惰两种情况,编写规则时需要特别注意。

  • 贪婪匹配(默认)
    及尽可能多的向后匹配,一直到把整个内容匹配完后再返回结果。
  • 懒惰匹配(加‘?’)
    及尽可能少的向后匹配,只要发现符合的就立即返回结果。
语法 说明
*? 重复任意此,但尽可能少重复
+? 重复1次或多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n次或m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

示例:
还是提取指定字符串str内容中,姓名‘张’什么‘峰’的。

//默认贪婪比配时无法正常提取出“张三峰”
var str ="张三峰的要去攀登珠穆朗玛峰";
var reo = /张[\u4e00-\u9fa5]*峰/g; //规则:张什么峰
var result = str.match(reo); //字符串的match()方法
alert(result) //提示:张三峰的要去攀登珠穆朗玛峰

//当我们加入懒惰匹配后就正常多了
reo = /张[\u4e00-\u9fa5]*?峰/g; //规则:张什么峰,中间懒惰比配
result = str.match(reo); 
alert(result) //提示:张三峰

修饰符

修饰符写在结束的/之后,可以影响整个正则表达式的匹配行为。
常见的修饰符如下:

符号 含义 说明
g 全局匹配 匹配所有项
i 忽略大小写 忽略英文字母的大小写
x 忽略空白 忽略内容中的空格
m 多行匹配 将有换行的内容视为多个值分别比配
s 单行匹配 转义回车换行符作为普通字符

全局模式

默认只返回第一个匹配项,全局模式返回所有匹配项。

示例:匹配字符串str中的所有数字。

var str = "a1b2c3";
var reo = /\d/; //表达式,匹配数字
alert(str.match(reo)) //提示:1
    
reo = /\d/g; //全局模式
alert(str.match(reo)) //提示:1,2,3

忽略大小写

在匹配时忽略英文字母的大小写。

示例:匹配字符串str中的所有字母(忽略大小写)。

var str = "A1b2c3";
var reo = /[a-z]/g; //表达式,全局匹配小写字母
alert(str.match(reo)) //提示:b,c
    
reo = /[a-z]/gi; //全局匹配小写字母,忽略大小写
alert(str.match(reo)) //提示:A,b,c

多行匹配

多行匹配|将有换行的内容视为多个值分别比配。

var str = 'a1b2c3'+'\n'+'321';
var reo = /^\d*$/g; //规则:匹配纯数字
alert(str.match(reo)) //提示:null
reo = /^\d*$/gm; //规则:匹配纯数字,多行匹配
alert(str.match(reo)) //提示:321

字符集

正则表达式提供一些常用的字符集及其简写, 见下表:

符号 简写 说明
[0-9] \d 数字,0到9
[^0-9] \D 非数字
[a-z] 小写英文字母
[A-Z] 大写英文字母
[a-zA-Z] 大小写英文字母
[a-zA-Z0-9_] \w 数字字母下划线
[^\W] \W 非数值字母下划线
[\r\t\n\f] \s 空白区域
[^\s] \S 非空白区域
[\u4e00-\u9fa5] 中文

其他符号

符号 含义 说明
\f 换页符
\n 换行符
\r 回车符
\t 制表符
\v 垂直制表符
\p CR/LF 等同于 \r\n

运算符优先级

正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式类似。
相同优先级的从左到右进行运算,不同优先级的运算先高后低。
具体见下表;(优先级从上至下排列)

运算符 描述
\ 转义符
()、(?: )、(?=)、[] 圆括号和方括号
*、 +、?、 {n}、 {n,}、 {n,m} 限定符
^、 $,、\任何元字符、普通字符 定位点和序列(即:位置和顺序)
|

深入学习

正则规则分组

及对比较复杂的规则进行细分为多个组,每个组实现对应的比配功能。这样及能使规则代码更易读,还能进阶更高大上的功能。最常见的就是对数据脱敏时的前后分组替换中间部分的操作。

以网站域名地址‘https://baidu.com’为例,主要由三部分组成:

  1. 协议https对于正则^\w{2,8}:/\/\
  2. 儿级域名baidu对应正则\s
  3. 顶级域名com

现在我们有一个匹配网站地址的正则:

\w{
    
    2,8}:/\/\

对现有正则进行分组:

获取单个分组的内容:

未完待续

常用的正则表达式整理


表单验证

  • 用户昵称
    可包含大小写字母、数字、下划线、中文;不能为空,长度不超过20位。
    [A-Za-z0-9_\u4e00-\u9fa5]{
          
          1,20}
    
  • 身份证号
    18位数的身份证=17位数字+1为数字或X结尾;
    或者15位数字(15位的身份证号大多数业务已经禁止使用了)。
    \d{
          
          17}[\d|x]|\d{
          
          15}
    
  • 手机号码
    1开头的11位数字(因为可能有新号段,就不做强匹配了)。
    1\d{
          
          10}
    
  • 邮箱地址
    已非特殊字符串开头+不定位数的非特殊字符串(含-.+)+'@'+大于一位的字母或数字(含-)+‘.’+2到14位字母或数字
    \w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{
          
          2,14}
    
  • 网址
    已常见网络协议开头接‘://’,不能包含空白符。
    ^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+
    
  • ip地址
    由四段数字组成,每段的值需满足ip对应规则,通过‘.’分割。
    (25[0-5]|2[0-4]\d|[0-1]\d{
          
          2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{
          
          2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{
          
          2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{
          
          2}|[1-9]?\d)
    

数据脱敏

前端脱敏并不可取,此处只为了展示脱敏方式,实际开发中请采用服务端脱敏。

  • 匿名
    不显示用户全名,只显示最后一位
    var str = "欧阳五爷";
    var reo = /.*(.{1})/; 
    //此处计算需要替换的位数
    var str1= "*";
    var len = str.length;
    while(len>1){
          
          
    	str1+="*";
        len--;
    }
    
    var result = str.replace(reo, str1+'$1');
    alert(result) //提示:***爷
    
  • 身份证号
    不显示出生日期
    var str = "110101199003073650";
    var reo = /(\d{6})\d{8}([0-9X]{4})/g; 
    var result = str.replace(reo, '$1********$2');
    alert(result) //提示:110101********3650
    
  • 手机号码
    不显示中间4位数
    var str = "13612345678";
    var reo = /(\d{3})\d{4}(\d{4})/g; 
    var result = str.replace(reo, '$1****$2');
    alert(result) //提示:136****5678
    

猜你喜欢

转载自blog.csdn.net/u011513460/article/details/108862876
今日推荐