正则表达式

正则表达式

概念

简单来说,正则表达式是一种字符串匹配的模式。再换句话说,正则表达式就是记录文本规则的代码,用来查找符合某种复杂规则的字符串的需要。

你可能用过Windows下的通配符,例如*和?,与通配符类似,正则表达式也是进行文本匹配的工具,只不过比起通配符,它会更加精确的匹配。当然,这也取决于你编写的正则表达式的复杂性。

元字符

正则表达式是通过元字符匹配的,那元字符是什么呢?元字符简单来说,就是正则表达式的匹配规则,拿几个来举例子:

元字符说明
.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\W匹配任意不是字母,数字,下划线,汉字的字符
\d匹配数字
[abcd]匹配abcd其中一个字符
[^abcd]匹配不是abcd的任意一个字符
[A-Z]匹配从A-Z中任意一个字符
[A-z]匹配从A-z任意一个字符(涵盖大小写)
^匹配字符串的开始
$匹配字符串的结束

以上只是几个常用的,真实用到的比上面的表格多得多。

其中^比较特殊,可以用来表示字符串的开始,如果放到[]中括号里,表示取反。

[]里面可以写单独一个字符,也可以写一个范围,举例子:

[a] 匹配A这个字符

[abcd] 匹配ABCD这几个字符中任意一个

[a-z] 匹配26个小写字符中的一个

[0-9] 这个跟\d一个意思,匹配0—9中任意一个数字

另外:这些元字符,区分大小写,大写表示取反,例如:\d匹配数字,\D匹配非数字。

字符转义

如果你想要匹配元字符本身的话,比如你想查找^,这时候你就需要用\来取消转义,两个\\匹配一个。

重复

我们前面知道\d匹配一个数字,那么如果我们想要匹配十个数字,应该怎么做?写十遍\d?

当然不会,正则表达式有几种限定符,用来匹配元字符出现的次数。

限定符说明
*重复0+次
+重复1+次
?重复0或1次
{n}重复n次
{n,}重复n+次
{n,m}重复n—m次

那上面我们说的十个数字,就是:\d{10}

分支条件

我们知道外国人的名字格式为:FirstName·LastName,也就是名·姓的格式。

但也有些外国人有中间名,也就是:FirstName·MiddleName·LastName

那我们怎么同时匹配这两种格式的外国人的名称呢?

很简单:

\w+[·]\w+|\w+[·]\w+[·]\w+

我们知道在程序中|表示或的关系,在这里也是,只要符合两个正则表达式的任意一个,都算符合条件。

分组

重复十个数字,我们知道怎么重复,直接\d{10}就行了。

但是如果让你重复多个字符呢?例如:abc重复十遍。

这时候就要用到分组了,分组的元字符是小括号()。

假设说我们要匹配一个IP地址,IP地址的格式我们知道,是这样的:

XXX.XXX.XXX.XXX

其中每一段都是0—255,也就是1位到3位

那我们的正则表达式就可以这么写:

(\d{1,3}\.){3}\d{1,3}

但是这会有一个问题,它会匹配到错误地址,例如:

999.999.999.999

那我们重新写一下:

((\d|\d{2}|1\d{2}|2[0-4]\d|25[0-5]).){3}\d|\d{2}|1\d{2}|2[0-4]\d|25[0-5]

这可能就比较复杂了,这个匹配了所有情况,1位的地址、2位的地址、100—199的地址,200—249的地址,250—255的地址

后向引用

其实每一个分组都会默认指定一个编号,就像我们前面写的(\d{1,3}\.)的默认编号就是1,从左到右,依次累加。

如果我上面的关于IP的分组是这么写的

(\d{1,3}\.)(\d{1,3}\.)(\d{1,3}\.)

那么依次的分组顺序就是1,2,3

如果现在有一段字符串是这种格式XXX-XXX-XXX,第一段和第三段都是英文字母,并且相同,第二段是数字,使用分组怎么描述呢?

你肯定会知道是用分组,第一组和第二组肯定这么写([A-z]{3})-(\d{3})-

到第三组的时候,你发现出现问题了:怎么保证第三组和第一组一样呢?

这时候我们就要用到后向引用了,因为我们知道,第一组的编号是1,那我们直接可以通过\1来引用第一组的值,也就是这样写:

([A-z]{3})-(\d{3})-\1

看结果:


1081094-20180903203941784-1312241245.png

匹配成功!

当然,你觉得用1,2,3...这种编号表示,有的时候会搞混,你也可以给分组起名,给分组起名的语法有两种:

(?<Group1>[A-z]{3}),第一种方式是在分组中最前方加?<Name>的方式起名

(?'Group1'[A-z]{3}),第二种方式是把<>换成'',也就是在分组中最前方加?'Name'的方式起名

这种情况是用<GroupName>或者'GroupName'的方式引用

把我们之前的正则表达式换一下:

(?<Group1>[A-z]{3})-(\d{3})-\<Group1>

(?'Group1'[A-z]{3})-(\d{3})-'Group1'

试一下:

1081094-20180903203959041-143518059.png

1081094-20180903204005093-1707310318.png

两种写法依旧匹配成功!

零宽断言

零宽断言用来指定一个位置,这个位置需要满足一些条件。

需要注意:零宽断言只匹配位置,而不会占用字符。

零宽先行断言:

全名:零宽度正预测先行断言

作用:匹配在某个表达式位置之前的符合条件的字符串

语法:(?=expression)

示例:

I am a competitor before.

匹配competitor这个单词,使用零宽先行断言可以这么写:

\b[A-z]+(?=\sbefore.)

1081094-20180903204014189-406798969.png

我们匹配到了 before.之前的单词,也就是competitor。

零宽后发断言

全名:零宽度正预测后发断言

作用:匹配在某个表达式位置之后的符合条件的字符串

语法:(?<=expression)

示例:

I am a competitor before.

匹配competitor这个单词,使用零宽后发断言可以这么写:

(?<=\b[a]\s)\b[A-z]+\b

1081094-20180903204045030-1381255316.png

我们匹配到了a 后面的单词,也是competitor.

负向零宽断言

前面我们说过,\后面跟大小写是取正和取反的区别,那有零宽断言,也当然有负向零宽断言,一听就知道是用来取反的,跟零宽断言一样,负向零宽断言也包含先行断言后发断言

负向零宽先行断言:

全名:负向零宽度正预测先行断言

作用:匹配不在某个表达式位置前面的字符串

语法:(?!expression)

示例:

ABC-123456-123-ABC

使用负向零宽先行断言,匹配第三段的的值:

\b\d{3}(?!\d)

结果:

1081094-20180903204053482-1084562994.png

负向零宽先行断言:

全名:负向零宽度正预测后发断言

作用:匹配不在某个表达式后面的字符串

语法:(?<!expression)

示例:

ABC-123456-123-ABC

使用负向零宽后发断言,匹配第三段的值:

(?<!123)\d{3}\b

结果:

1081094-20180903204103233-1579244729.png

贪婪与懒惰

当你使用正则表达式来匹配字符的时候,它都会尽量多的匹配,这种方式称为贪婪匹配原则,也是默认的匹配模式。

示例:

abcabcab这个字符串,如果使用^.*b,它会直接匹配整个字符串。

1081094-20180903204143871-1183278607.png

而我们只希望它匹配第一个ab,也就是常说的懒惰匹配原则,这时候需要在后面加一个?

也就是^.*?b,匹配的结果就是ab。在普通限定符后面加上?,就会变成懒惰限定符

1081094-20180903204156638-2141502032.png

鉴定符说明
*?重复任意次,但尽可能少重复
+?重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复


其他

我们今天学习的只是正则表达式语法,但是在实际开发中,会有很多血想,例如:区分大小写、多行匹配、单行匹配、忽略空白等,这都取决于开发平台提供的API的支持,就写这么多吧,实在啃不动了...
之前学的都快忘了,再复习一遍...

大部分内容摘自及参考:http://deerchao.net/tutorials/regex/regex.htm,16年我就读的他写的关于正则表达式的文章,如今回来还是读他的,经典
测试工具下载地址:http://deerchao.net/tools/regester/index.htm

转载于:https://www.cnblogs.com/Fill/p/9580789.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值