在线测试:https://tool.oschina.net/regex/
vba正则表达式入门
正则表达式从后向前匹配
正则表达式很强大且内容比较多。不少初学者学这个表示很困难。故写一篇入门的教程。
1、什么是正则表达式
正则表达式是一个天才创建的用于快速检索匹配字符串,通过简单的表达式匹配文本。
2、正则表达式的组成
正则表达式也是一个字符串,包括元字符、限定符和正常意义的字符。正则表达式强大的地方就在元字符和限定符。
3、限定符
很多人讲这个都是先讲元字符。其实先讲限定符更加容易吸收。限定符是表示前面字符或元字符出现的次数。主要限定符如下:
限定符 含义
* 表示前面字符或元字符出现0次或多次。例如:zo*m,可以匹配zm,zom,zoom
+ 表示前面字符或元字符出现1次或多次。例如:zo+m,可以匹配zom,zoom
? 表示前面字符或元字符出现0次或1次。例如:zo?m,可以匹配zm,zom
{n} 表示前面字符或元字符出现n次。例如:zo{3}m,可以匹配zooom
{n,m} 表示前面字符或元字符出现n到m次。例如:zo{1,3}m,可以匹配zom,zoom,zooom
{n,} 表示前面字符或元字符至少出现n次。例如:zo{2,}m,可以匹配zoom,zooom等等
当然,限定符用法不止这些。正则表达式还有个规则叫贪婪与吝啬。有些人也叫贪婪与懒惰。这个“贪婪与吝啬”是正则表达式难点和重点之一。
例如,字符串“n123n456n789n”。那么我们怎么匹配获取“n123n”和“n123n456n789n”呢。
使用正则表达式,首先要找规律。很明显我们要获取的内容开头和结尾都有一个字母n,中间是数字或字母。我们先学一个元字符。元字符是可以代表一定含义或规律的字符。可以匹配除了换行符之外的任意字符是小数点。
那么我们的表达式可以这么写:n.+n
两个字母n,中间夹着1个或多个任意字符。
但这样只能匹配得到一个结果:n123n456n789n。在我们没有对其任何限制的情况下,正则表达式会尽可能多匹配符合条件的结果。从头到尾整个都符合,所以都匹配了。这个称之为贪婪匹配。
那如何做到尽可能少的匹配。这个就需要加个?进行限制。
例如,表达式:n.+?n
这个表达式尽可能少匹配,也就是说碰到一次符合条件的就立马返回结果。结果可以匹配到“n123n”、“n789n”。
这种规则叫做吝啬匹配。只要在限定符后面再加个问号即可。
4、元字符
元字符是用于匹配字符串,可以代表一定含义或规律的字符串。主要的元字符如下:
元字符 含义
. 小数点,代表除了换行符以外的任意字符
\ 转义,若我想匹配一些被正则表达式占用的字符,例如小数点,可以用\.
[abc] 匹配中括号内的字符,例如[a-zA-Z],可以匹配到大小写字母
[^abc] 不匹配中括号内的字符,例如[^a-z],表示不匹配小写字母
\w 可以匹配字母、下划线和数字,相当于[a-zA-Z0-9_]
\W 大写的W是小写的w相反情况,也就是不匹配字母、下划线和数字。相当于[^a-zA-Z0-9_]
\s 匹配任意空白符,相当于[\f\n\r\t\v]
\S 匹配任意非空符,相当于[^\f\n\r\t\v]或[^\s]
\d 匹配数字,相当于[0-9]
\D 匹配非数字,相当于[^0-9]
\b 匹配单词的边界。这个匹配英文单词特别有用。例如\b[\w']+?\b就可以匹配任意单词了
\f 匹配换页符
\n 匹配换行符
\r 匹配回车符
\t 匹配tab制表符
\v 匹配垂直制表符
^ 不在中括号内的^,表示从字符串的开头开始匹配
$ 表示匹配到字符串的结尾
x|y 匹配x或y
(表达式) 元组,用小括号括起来的表达式当作一个元组,可以当作一个整体,也可以被\1\2\3这样类似索引获取。
元字符比较多,这里就建议大家先收藏,需要用的时候再查阅。多用几次就自然记住了。
这里还有个小技巧,若我想匹配全部任意字符,包括换行符。可以用一组相反的元字符,例如[\s\S],就可以匹配全部任意字符。
5、常见的正则表达式
说了这么多,晕了没?看一些实例:
1)匹配邮编,邮编是6位数字。正则表达式:\d{6}
2)匹配手机,手机号是11位数字。正则表达式:\d{11}
3)匹配电话,电话是区号-号码组成,区号有3到4位,号码有6到9位。正则表达式:\d{3,4}-\d{6,9}
4)匹配日期,日期格式如1992-5-30,明显数字加横线组成。正则表达式:\d{4}-\d{1,2}-\d{1,2}
5)匹配汉字,汉字需要通过编码转义,汉字都unicode编码中都在一个范围内。正则表达式:[\u4e00-\u9fa5]
6、vba中使用正则表达式
若只是上面这些内容,那么还是纸上谈兵,需要应用到实际中。看看如何在vba中使用正则表达式。
vba使用正则表达式需要用到一个RegExp对象。
该对象可以通过引用Microsoft VBScript Regular Expressions 5.5。再声明定义:
Dim reg As New RegExp
还可以直接用CreateObject方法创建:
Dim reg As Object
set reg = CreateObject("VBScript.Regexp")
创建RegExp对象之后,看看它的相关属性和方法。
属性:
1)Global,是否全局匹配,若为False,匹配到一个结果之后,就不再匹配。默认False,建议设为True;
2)IgnoreCase,是否忽略大小写,默认False,建议设为False,这个会影响到正常表达式匹配;
3)Multiline,是否跨行匹配,默认False,建议设为False,这个会影响到正常表达式匹配;
4)Pattern,获取或设置正则表达式。
方法:
1)Execute,执行匹配
2)Replace,根据正确表达式全部替换
3)Test,测试正则表达式能否匹配到内容
举一些典型的例子:
1)判断是否存在数字
Public Function CheckNumber(str As String) As Boolean
Dim reg As Object
Set reg = CreateObject("VBScript.Regexp")
Dim is_exist As Boolean
With reg
.Global = True
.Pattern = "\d"
is_exist = .Test(str)
End With
CheckNumber = is_exist
End Function
用Test方法,判断能否匹配到数字。
2)获取所有编号
Public Sub GetCode()
Dim reg As Object
Set reg = CreateObject("VBScript.Regexp")
Dim str As String
str = "编号:ABC123155 日期:2016-01-11" & _
"编号:ABD134215 日期:2016-02-21" & _
"编号:CBC134216 日期:2016-01-15"
reg.Global = True reg.Pattern = "[A-Z]{3}\d+" '获取匹配结果'
Dim matches As Object, match As Object
Set matches = reg.Execute(str)
'遍历所有匹配到的结果'
For Each match In matches
'测试输出到立即窗口'
Debug.Print match
Next
End Sub
因为这个编号是3个大写字母和多个数字组成。可以利用代码中的表达式匹配到3个结果:ABC123155、ABD134215和CBC134216。
3)去掉字符串中的数字
Public Function ClearNumber(str As String) As String
Dim reg As Object
Set reg = CreateObject("VBScript.Regexp")
reg.Global = True
reg.Pattern = "\d"
'把所有数字替换成空'
ClearNumber = reg.Replace(str, "")
End Function
执行ClearNumber函数,即可去掉数字。例如ClearNumber("你342好234啊"),可得到"你好啊"。
4)获取子字符串
例如想获取某些字符串中的部分数据,可以匹配完成之后,再用字符串函数处理。但其实不用,用元组可以一次性搞定。
Public Sub GetHref()
Dim reg As Object
Set reg = CreateObject("VBScript.Regexp")
Dim str As String
str = "<a href='xxx1'>xxx1</a><a href='xxx2'>xxx2</a>"
reg.Global = True
'获取a标签中href的属性值'
reg.Pattern = "href='(.+?)'"
'获取匹配结果'
Dim matches As Object, match As Object
Set matches = reg.Execute(str)
'遍历所有匹配到的结果'
For Each match In matches
'测试输出子表达式到立即窗口'
Debug.Print match.SubMatches(0)
Next
End Sub
这里,可以通过match的SubMatches集合获取元组里面的内容。轻松得到xxx1和xxx2。
7、其他说明
vba的正则表达式不是很完整,没有递归的功能。递归是可以匹配公式或html代码等。有兴趣可以了解一下。
————————————————
版权声明:本文为CSDN博主「gerald2008」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gerald2008/article/details/116233205
1 正则表达式必知必会
1.1 简介
正则表达式:是一些用来匹配和处理文本的字符串。
正则表达式的使用场景主要以下两种情况:一是查找特定的信息(搜索),二是查找并编辑特定的信息(替换)。
用模式(pattern)表示实际的正则表达式。
1.2 匹配单个字符
匹配普通文本:正则表达式为待匹配的文本。
匹配任意字符:.字符(英文句号)可以匹配任意单个字符,如字符、字母、数字,甚至是.字符本身。
匹配特殊字符:使用转义地字符,如.。
1.3 匹配一组字符
匹配多个字符中的某一个
使用[]定义一个字符集合,对于连续字符使用-连字符来定义字符区间。集合内字符是OR关系,匹配其中之一。
[A-Z]:匹配从A到Z的所有大写字母。
[a-z]:匹配从a到z的所有小写字母。
[0-9]:匹配从0到9的所有数字。
排除
使用元字符^来排除字符集合里指定的那些字符,如[^0-9]。注意,^的效果将作用于给定字符集合里的所有字符或字符区间。
1.4 使用元字符
1.4.1 元字符转义
元字符:在正则表达式里有特殊含义的字符。
转义:元字符可以通过在前面加上一个反斜杠()进行转义,这样匹配的就是该字符本身而不是特殊的元字符含义。
1.4.2 匹配空白字符
元字符大概可以分为两种:一种是用来匹配文本的(如.),另一种是正则表达式语法的组成部分(如[])。
空白元字符:换页符(f)、换行符(n)、回车符(r)、制表符(t)。
一般来说,需要匹配r、n和t等空白字符的情况比较多见。rn匹配一个回车+换行组合。
1.4.3 匹配特定的字符类型
匹配数字与非数字:
d:任何一个数字字符(等价于[0-9])
D:任何一个非数字字符(等价于[^0-9])
匹配字母数字或下划线:
w:任何一个字母数字或下划线字符(等价于[a-zA-Z0-9_])
W:任何一个非字母数字或非下划线字符(等价于[^a-zA-Z0-9_])
匹配空白字符与非空白字符:
s:任何一个空白字符(等价于[fnrtv])
S:任何一个非空白字符(等价于[^fnrtv])
1.5 重复匹配
匹配一个或多个字符:
+匹配一个或多个字符,在一个给定字符集合加上+后缀时,必须放在整个字符集合的外面,如[0-9]+。
一般来说,当在字符集合使用时,像.和+这样的元字符被解释为普通字符,不需要转义,但转义也不影响。
匹配零个或多个字符:
*用来匹配字符或字符集合出现零次或多次的情况。
匹配零个或一个字符:
?可以匹配某个字符或字符集合的零次或一次。
[]的常规用法是把多个字符定义为一个集合,但不少程序员喜欢把一个字符也定义为一个集合,好处是可以增加可读性和避免产生误解。同时使用[]和?时,要把?放在字符集合的外面。
具体的匹配次数:
设置具体的匹配次数,把数字写在{}中,如{3}。
可以为重复匹配的次数设定一个区间范围,设置最小次数和最大次数,如{3, 5}。
也可以指定至少要匹配的次数,如{3, }。
防止过度匹配:
在使用重复匹配如果没有上限值,则有时会导致过度匹配的现象。
像*和+这些都是“贪婪型”元字符,其匹配行为是多多益善和不是适可而止,会尽可能从一段文本的开头一直匹配到末尾,而不会碰到第一个匹配时就停止。
+、*、?这些叫做量词,量词是贪婪的。
为了防止过度匹配,我们可以使用量词的“懒惰型”版本(匹配尽可能少的字符,而非尽可能多地去匹配),懒惰型量词地写法是在贪婪型量词后加?。
1.6 位置匹配
位置匹配用于指定应该在文本什么地方进行匹配操作。位置匹配需要用到边界,即一些用于指定模式前后位置(或边界)的特殊元字符。
单词边界
由b指定单词边界,用来匹配一个单词的开头或结尾。b匹配的是字符之间的一个位置:一边是单词(能够被w匹配的字母数字和下划线),另一边是其他内容(能够被W匹配的字符)。注意:b匹配的是一个位置,而不是任何实际的字符。
如果我们想匹配一个完整的单词,就必须在匹配的文本前后加上b。如果不想匹配单词边界,可以使用B。
字符串边界
字符串边界元字符有两个:^表示字符串开头,$表示字符串结尾。
注意:有些元字符有多种用途,如^。如果^出现在字符集合[]里且紧跟在左方括号[后面时,它才表示排除该字符集合。如果^出现在字符集合之外并且位于模式的开头,^将匹配字符串的起始位置。
多行模式
多行模式影响的是^和$的匹配规则:在默认模式下,^和$匹配的是整个字符串的起始位置和结束位置,但是在多行模式下,它们也能匹配字符串内部某一行文本的起始位置和结束位置。多行模式迫使正则表达式引擎将换行符视为字符串分隔符,这样一来,^既可以匹配字符串开头,也可匹配换行符之后的起始位置(新行);$不仅能匹配字符串结尾,也能匹配换行符之后的结束位置。
启用多行模式,使用(?m),并且其必须出现在整个模式最前面。
1.7 子表达式
子表达式是更长的表达式的一部分。划分子表达式的目的是为了将其视为单一的实体来使用。子表达式使用()进行定义,并用于对表达式进行分组。
指定子表达式的重复次数
匹配IP:(d{1, 3}.){3}d{1, 3}
与模式里的|(或)连用
(19|20)d{2},匹配19或20开头的年份。
子表达式的嵌套
匹配一个有效的IP:
(((25[0-5])|(2[0-4]d)|(1d{2})|(d{1, 2})).){3}(((25[0-5])|(2[0-4]d)|(1d{2})|(d{1, 2})))
1.8 反向引用
反向引用:指的是这些实体引用的是先前的子表达式。
使用小括号()指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。
默认组号
默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。1是引用匹配模式中使用的第一个子表达式,2匹配模式中的第二个子表达式,以此类推。0可以用来匹配整个表达式。
自定义子表达式的组名
(?<name>exp)或(?'name'exp):匹配exp,并捕获文本到名称为name的组里。
匹配但不捕获,也不分配组号
(?:exp):匹配exp,不捕获匹配的文本,也不给此分组分配组号。
1.9 环视
向前查看
向前查看指定了一个必须匹配但不用在结果中返回的模式。向前查看是查看以匹配文本之后的内容,但不消耗这些内容。向前查看是一个子表达式,以?=开头,需要匹配的文本跟在=的后面。例如:.+(?=:)可以匹配http://www.baidu.com,https://www.baidu.com/中的http和https。
向后查看
向后查看是查看以匹配文本之前的内容,操作符为?<=。
以上两个都属于肯定式查看,与之相对应的是否定式查看,即否定式向前查看和否定式向后查看。
否定式向前查看
否定式向前查看会向前查看不匹配指定模式的文本,操作符为?!。
否定式向后查看
否定式向后查看是向后查看不匹配指定模式的文本,操作符为?<!。
1.10 嵌入式条件
正则表达式里的条件用?来定义。嵌入式条件主要以下两种情况:一是根据反向引用来进行条件处理,二是根据环视来进行条件处理。
反向引用条件
反向引用条件仅在一个前面的子表达式得以匹配的情况下才允许使用另一个表达式。定义这种条件的语法是(?(backreference)true),其中?表明这是一个条件,括号里的backreference是一个反向引用。
条件还可以使用else表达式,定义这种条件的语法:(?(backreference)true|false)。
示例:(()?d{3}(?(1))|-)d{3}-d{4}
环视条件
环视条件允许根据向前查看或向后查看操作是否成功来决定要不要执行表达式。
示例:d{5}(?(?=-))-d{4}
1.11 正则表达式测试网站
http://www.pyregex.com/
https://regex101.com/
https://c.runoob.com/front-end/854
————————————————
版权声明:本文为CSDN博主「小白便当」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_26766909/article/details/113412649