赞
踩
正则表达式(RegExp)是一种匹配字符串书写格式的专用表达式,由于它体积小,执行效率高,正则表达式也被集成到很多编程语言中,在C、C++、Java、JavaScript都有应用
!> 本教程是以JavaScript为基础讲解正则表达式,若使用其他编程语言,可以选择性的参考本教程
在学习正则表达式之前,我们首先要了解JavaScript
对正则表达式的支持
用途:
用来验证字符串
是否匹配正则表达式
,匹配则返回true,不匹配则返回false
语法:
RegExp.test(String)//返回true/false
案例:
// 该正则表达式的含义是匹配5个数字
var reg=/\d{5}/
var str="12345"
console.log(reg.test(str))// true
用途:
用来返回字符串
匹配正则表达式
的结果
语法:
String.match(RegExp)//返回一个匹配结果数组或匹配详情
案例:
// 该正则表达式表示匹配所有的数字
var reg=/\d/g
var str="abc123g3b445gbh331"
console.log(str.match(reg))// [1,2,3,3,4,4,5,3,3,1]
!> 注意:match()和test()不同,match前面是字符串,后面是正则表达式
用途:
用来替换符合正则表达式的文本
语法:
String.replace(RegExp,String)//返回一个替换后的字符串
案例:
// 正则表达式含义:匹配所有数字
var reg=/\d/g
var str="abc123tyu678"
// 将所有的数字替换成*
str=str.replace(reg,'*')
console.log(str)// abc***tyu***
!> 注意:replace方法不会修改字符串本身,而是返回一个替换结果
用途:
用来查找匹配结果的位置
语法:
String.search(RegExp)//返回索引值
案例:
// 正则表达式含义:匹配所有数字
var reg=/\d/
var str="abcf3ght"
console.log(str.search(reg))// 4
通过上面内容的学习,我们了解了JS对于正则表达式的支持,那么现在就正式学习正则表达式吧。
创建正则表达式我们有两个选择:
// \d代表一个数字,这个正则表达式是匹配数字的意思
var reg=/\d/
// 为什么要写两个\\,这是因为\在字符串中有转义含义,\\相当于一个\,%%相当于%
var reg=new RegExp("\\d")
字符串其实就是最简单的正则表达式,比如我们想要匹配一个人的名字,我们就可以把这个人的名字作为正则表达式
模糊匹配指的是,只要包含这个内容就可以,不需要完全符合
// 匹配张三
var reg=/张三/
var name1="张三"
var name2="李四"
var str="我叫张三,我今年18岁了"
// test用于测试字符串是否符合正则表达式
console.log(reg.test(name1),reg.test(name2),reg.test(str))// true false true
!> 看起来可以实现匹配姓名的功能,不过其实它是有问题的,因为他是模糊匹配,不精确
// 假如有个人叫张三丰,那么匹配结果会怎么样呢
var reg=/张三/
var name="张三丰"
console.log(reg.test(name))// true
这是为什么呢?原因是模糊匹配只要匹配到了就可以,由于张三丰包含张三,所以返回true
看起来模糊匹配并不能解决匹配姓名的问题,下面就要有请精准匹配了
精准匹配要求的是匹配内容必须完全符合,包含关系不可以,必须全等
语法:在正则表达式的开头加上^,结尾加上$
var reg=/^张三$/
console.log(reg.test("张三"),reg.test("张三丰"))// true false
使用了精准匹配过后,我们就可以匹配到精确的结果了
我们有些时候想匹配以xxx开头的句子,那我们需要怎么写呢?
语法:在正则表达式的开头加上^
// 匹配以猫开头的正则表达式
var reg=/^猫/
var str1="猫是一种哺乳动物,它很可爱"
var str2="我喜欢猫,我养了很多只"
console.log(reg.test(str1),reg.test(str2))// true false
!> ^的含义是匹配开头
我们有些时候想匹配以xxx结尾的字符串,那我们怎么写呢?
语法:在正则表达式的结尾加上$
// 匹配以txt结尾的字符串
var reg=/txt$/
var str="hello.txt"
var str1="txt.ppt"
var str2="helloworldtxt"
console.log(reg.test(str),reg.test(str1),reg.test(str2))// true false true
!> $的含义是匹配结尾
你可能会想为什么我们不写.txt作为正则表达式呢,因为.在正则表达式中有特殊含义,它表示任意一个字符
如果我们想使用.让它只是表示点的含义,而不是任意一个字符,就需要对它进行转义:使用\.
特殊符号 | 表示含义 |
---|---|
. | 任意一个字符 |
\. | 表示小数点. |
所以我们可以这样修改我们的正则表达式
// 匹配.txt文件
var reg=/\.txt/ // \.表示. .表示任意一个字符
var str="hello.txt"
var str1="txt.ppt"
var str2="helloworldtxt"
console.log(reg.test(str),reg.test(str1),reg.test(str2))// true false false
!> 在正则表达式中特殊字符的转义都是使用\加那个字符
在正则表达式中,我们有四种匹配模式
局部匹配指的是我们只匹配第一个出现的结果,匹配到了就不往下匹配了
// 举个例子:我们需要替换小明,把小明替换为小红
var str="小明是一个好孩子,小明成绩优异,小明是班长"
// 匹配小明
var reg=/小明/
// 使用JSAPI=>replace进行替换
console.log(str.replace(reg,"小红"))
// 结果:小红是一个好孩子,小明成绩优异,小明是班长
!> 总结:单一匹配只匹配第一个出现的结果
全局匹配指的是我们要查找全部的匹配结果,而不是匹配到了一个就不往下匹配了
语法:使用/g,g是英文global的缩写
// 举个例子:我们需要替换小明,把小明替换为小红
var str="小明是一个好孩子,小明成绩优异,小明是班长"
// 使用g启动全局匹配
var reg=/小明/g
// 使用JSAPI=>replace进行替换
console.log(str.replace(reg,"小红"))
// 结果:小红是一个好孩子,小红成绩优异,小红是班长
!> 总结:全局匹配匹配所有符合条件的结果
var reg=/a/i
var str="a"
var str1="A"
console.log(reg.test(str),reg.test(str1))
!> 忽略大小写匹配,会忽略大小写
元字符是一个字符的集合,它表示集合内的任何一个字符。
[字符集]
匹配一个数字:[0-9]或[0123456789]
匹配一个小写英文:[a-z]或[abcdefghijklmnopqrstuvwxyz]
匹配一个大写英文:[A-Z]或[ABCDEFGHIJKLMNOPQRSTUVWXYZ]
匹配一个英文字符的话:[a-zA-Z]或[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]
!> 如果是ASCLL码相邻的字符,可以用-简写
// 匹配一个数字
var reg=/[0-9]/
var num="1"
var num1="2"
var charset="a"
var format="^"
console.log(reg.test(num),reg.test(num1),reg.test(charset),reg.test(format))// true true false false
!> 元字符只能代表这个特征范围内的一个字符,如果想要匹配这个范围内的多个字符,就需要引入量词
量词用来修饰元字符,用来限制元字符出现的频率
[字符集]{min,max} 表示元字符最少出现min次,最多max次
[字符集]{min,} 表示元字符最少出现min次,最多没有限制
[字符集]{count},表示元字符必须出现count次
匹配至少3个数字:[0-9]{3,}
匹配2-5个数字:[0-9]{2,5}
// 匹配手机电话号码 手机电话号码特征是11位数字
// 开启精准匹配,防止14位包含13位匹配的情况
var reg=/^[0-9]{11}$/
var phone="13253678799"
var str="123456789"
console.log(reg.test(phone),reg.test(str))// true false
正则表达式也会有与或非的基本逻辑关系
与表示既要满足这个也要满足那个,与是正则表达式默认的逻辑模式
比如:我想匹配数字和英文字母(包括大小写)
/[0-9][a-z][A-Z]/
!> 与的话就是直接串起来就行
或表示这也行,那个也行
比如:我想匹配音频文件,音频格式的话后缀.mp3可以,.ogg可以,.wav也行
/\.mp3|\.ogg|\.wav$/
!> 或的话用|表示
非的话表示除了这个之外都行,在正则表达式中非只能在元字符中使用
// 表示除了数字以外都行
/[^0-9]/
// 表示除了英文都行
/[^a-zA-Z]/
!> 在//双斜杠中的含义是匹配开头的意思,在[ ]元字符中的含义是非
某些特殊的元字符是可以简写的
原始写法 | 简写 | 含义 |
---|---|---|
[0-9] | \d | 匹配一个数字 |
[^0-9] | \D | 匹配除了数字任何一个字符 |
[0-9a-zA-Z] | \w | 匹配英文和数字中任何一个字符 |
[^0-9a-zA-Z] | \W | 匹配除了英文和数字中任何一个字符 |
[\r\n\f\t] | \s | 匹配换行符、空格等空白字符 |
[^\r\n\f\t] | \S | 匹配非空白字符 |
\w通常被认为匹配文本 因为在使用英文国家里数字 英文就是文本
匹配至少出现5个数字,开头必须是英文
/^[a-zA-Z]{1,}\d{5,}/
某些特殊的量词也是可以简写的
原始写法 | 简写 | 含义 |
---|---|---|
{0,1} | ? | 出现频率0或1次(可有可无) |
{0,} | * | 不出现或者出现任意次 |
{1,} | + | 至少出现一次 |
匹配整数或小数
/^-?\d+\.?(\d+)?$/
这个正则表达式就是表示的整数或者小数,加括号是对这个整体进行量词修饰
var reg=/^-?\d+\.?(\d+)?$/
var num="12"
var dic="3.14"
var str="3.14abd"
console.log(reg.test(num))
console.log(reg.test(dic))
console.log(reg.test(str))
!> 正则表达式和因式分解一样,可以进行提取公因式
// 匹配整数和小数,提取公因式版
var reg=/^-?\d+(\.\d+)?$/
var num="12"
var dic="3.14"
var str="3.14abd"
console.log(reg.test(num))
console.log(reg.test(dic))
console.log(reg.test(str))
因式分解前
/^-?\d+\.?(\d+)?$/
因式分解后
/^-?\d+(\.\d+)?$/
!> 因式分解可以可以简化正则表达式
正则表达式可以进行分组,这样我们可以用$1、$2…来获取它们的匹配值
(正则表达式1)(正则表达式2)…
使用括号包裹
var reg=/(\d+)([a-z]+)([A-Z]+)/
var str="123abcABCDEF"
reg.test(str)
// 分别获取匹配结果的全部匹配结果、第一组、第二组、第三组的匹配结果
console.log(str.match(reg),str.match(reg)[1],str.match(reg)[2],str.match(reg)[3])
// 我们也可以利用RegExp直接获取它们的分组匹配结果
console.log(RegExp.$1,RegExp.$2,RegExp.$3)
// 输出结果为 123 abc ABCDEF
!> 只要使用了JSAPI,RegExp就会被激活,上面案例使用了test,激活了RegExp
未被激活的RegExp里面内容为undefined ex:RegExp.$1->undefined
上面我们书写了匹配整数或小数的正则表达式
/^-?\d+(\.\d+)?$/
由于这个正则表达式有括号,是正则分组的语法,于是我们便可以轻松的获取匹配结果的小数部分
var reg=/^-?\d+(\.\d+)?$/
reg.test("3.14")
console.log(RegExp.$1)// .14
通过RegExp的基础学习我们了解到了,正则表达式的一些基础特点。那么下面我们来进一步深入学习正则表达式
现在有一个需求,有一串文字,我们要把所有的中文查找出来,然后翻译成英文,之后替换原来的中文,使得通篇都是英文。来保证英国人可以看懂中文网站
这就是谷歌翻译做的事情,现在我们要实现它。当然翻译需要翻译接口,这里可以自行百度,但是这可能要收费,不过网上也有很多破解方法。
// 对于匹配中文的话我们只能使用unicode编码进行匹配
/[\u4e00-\u9fa5]/
// 这个unicode范围匹配是汉字
替换汉字内容(模拟谷歌翻译)
var reg=/[\u4e00-\u9fa5]/g
var str="我是postman,大家好"
console.log(str.replace(reg,"ki "))
现在我有一个需求,对于字符串“abcdefg”,我想给它们的缝隙添加一个+号,也就是变成+a+b+c+d+e+f+g+
这个就是属于边界匹配的内容了,对于正则表达式而言,我们不仅可以匹配原文内容,原文之间的分隔我们也可以进行操作
原始写法 | 简写 | 含义 |
---|---|---|
()() | \b | 表示空位 |
!> \b表示字符串的边界
// 匹配空位 开器全局模式/g
var reg=/()()/g
// 字符串abcdefg
var str="abcdefg"
console.log(str.replace(reg,"+"))//+a+b+c+d+e+f+g+
var str1="abc 你好 你a好b"
console.log(str1.replace(reg,"-"))//-a-b-c- -你-好- -你-a-好-b-
!> 边界其实就是缝隙
在学习零宽断言之前,我们请看一个例子
我们现在有个字符串:张家屯的小王和苏家屯的小王是好朋友
现在我想匹配张家屯的小王,不想匹配苏家屯的小王,怎么办?
这个时候我们就需要使用零宽断言了
// ?<=张家屯的,表示前面必须是张家屯
var reg=/(?<=张家屯的)小王/g
var str="张家屯的小王和苏家屯的小王是好朋友"
var res=str.replace(reg,"小李")
console.log(res)
!> (?<=)是零宽断言,它可以修饰匹配对象,表示小王前面必须是张家屯的
零宽的意思是它不占据匹配结果
/(?<=张家屯的)小王/g
匹配的其实还是小王,没有张家屯的
var reg=/(?<=张家屯的)小王/g
var str="张家屯的小王"
var res=str.match(reg)
console.log(res)// ["小王"]
但是/(张家屯的)(小王)/g
匹配的却是包含张家屯的,是占据匹配宽度的
var reg=/(张家屯的)(小王)/g
var str="张家屯的小王"
var res=str.match(reg)
console.log(res)// ["张家屯的小王"]
!> 零宽是不占据匹配结果的,正常的分组是占据匹配结果的
断言是用来修饰匹配内容的,要求匹配内容必须符合xxx条件。
就像/(?<=张家屯的)小王/g
一样,不是所有的小王都行,必须前面是张家屯的才行,这就是断言
修饰语在前面的断言叫前置断言
// 匹配猫,且前面的修饰必须是聪明的
var reg=/(?<=聪明的)小猫/
var str="可爱的小猫,聪明的小猫,懒散的小猫"
console.log(str.replace(reg,"小猫咪咪"))// 可爱的小猫,聪明的小猫咪咪,懒散的小猫
修饰语在后面的断言叫后置断言
// 匹配猫,且后面的修饰必须是很开心
var reg=/小猫(?=很开心)/
var str="我养了一致小猫,小猫会玩耍,小猫很开心"
console.log(str.replace(reg,"小猫咪咪"))//我养了一致小猫,小猫咪咪会玩耍,小猫很开心
!> 断言可以理解为形容词,是对匹配内容的修饰
零宽断言是指既不占据匹配结果,又能起到修饰名词作用的断言
常见的零宽断言如下
零宽断言 | 断言类型 | 备注 |
---|---|---|
?<= | 前置断言 | 表示前面必须是xxx |
?<! | 前置断言 | 表示前面不能是xxx |
?= | 后置断言 | 表示后面必须是xxx |
?! | 后置断言 | 表示后面不能是xxx |
?!^ | 前置断言 | 忽略首位的匹配结果 |
?!$ | 后置断言 | 忽略末位的匹配结果 |
var str="123456"
var reg=/(?!^)\d(?!$)/g
console.log(str.match(reg))// 2345
现在我想获取下面这个标签的class属性值
<div class="navBar"></div>
使用正则
var reg=/(?<=class\=\").+(?=\")/g
var html=`<div class="navBar"></div>`
console.log(html.match(reg))
我们使用\= 是为了转义=;使用\“是为了转义”;\w+是指很多个文字,.指的是任意一个字符(不包括一些特殊字符)
比如现在我想筛选下面h1标签内的文字
<h1>标题一</h1>文本<h2>标题二</h2>
我们可能要这样写正则表达式
var reg=/(?<=\>).*(?=<)/g
var str=`<h1>标题一</h1>文本<h2>标题二</h2>`
console.log(str.match(reg))//标题一</h1>文本<h2>标题二
从匹配结果我们可以看到,他就是特别的贪婪,一直匹配到底了
那么如何解决这个问题呢?
我们可以使用量词巧妙解决:
// 加一个?,就解决了。?是可有可无的意思
var reg=/(?<=\>).*?(?=<)/g
var str=`<h1>标题一</h1>文本<h2>标题二</h2>`
console.log(str.match(reg))// ["标题一","文本","标题二"]
!> .*?这个组合被称之为非贪婪匹配,可以使得正则不再贪婪,是见好就收,而不是一贪到底
现在有一个比较大的数字:1234567,你需要把它处理成1,234,567
也就是说每三位为一个分隔,从低位到高位进行分隔
function formatPrice(price){
var reg=/(?!^)(?=(\d{3})+\b)/g
return price.toString().replace(reg,",")
}
console.log(formatPrice(1234567)) //1,234,567
\b是边界,指的是最右边的边界
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。