.NETCore C# 中级篇2-4 一文带你完全弄懂正则表达式
.NETCoreCSharp 中级篇2-4
本节内容为正则表达式的使用
简介
有的时候,你是否有过这种需求:判断一个Ip地址、邮箱、密码规则是否合法。如果让你使用if一类的传统方法进行处理,你肯定会被逼疯的。而对于绝大多数的编程语言而言,都有一个字符串处理利器————正则表达式。它可以轻松的让字符串和规则匹配上。有点这样的意思,从前你是判断字符串,去遍历它,而有了正则表达式,你是在书写一个通用性质的规则,让字符串与规则进行匹配。正则表达式本质上就是一串蕴含了一些特殊字符规则的字符串,因此我们书写正则表达式其实是在书写一个字符串,只是它代表了一定的规则而已。
常见的几种正则符号
事实上正则表达式没有过多的知识点,只是一些技巧性的训练,但请相信我,正则表达式是非常重要的。熟练的使用下列的正则符号会对你大有脾益。
元字符
元字符 | 说明 |
---|---|
. | 匹配除了换行符以外的任意字符 |
\w | 匹配字母、数字、下划线以及汉字 |
\s | 匹配任意空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
1.例如匹配abc开头的字符串
\babc 或者 ^abc
2.匹配5位数字的字符串
^\d\d\d\d\d$
重复限定符号
有了元字符就可以写不少的正则表达式了,但细心的你们可能会发现:别人写的正则简洁明了,如果你只使用元字符进行正则表达式的书写,既不美观也不实用,因此我们使用重复限定符进行重复数据的处理,下面我们来看一些限定符:
字符 | 说明 |
---|---|
* | 重复0次或多次 |
+ | 重复一次或一次以上 |
? | 重复0次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
现在我们就能书写相当美观的正则表达式了,例如:
1.匹配7位数字的电话号码
^\d{7}$
2.匹配138开头的手机号
^138\d{8}
3.匹配a开头,若干个b结尾的字符串
^ab*$
分组
现在我们已经学会以一点关于书写正则表达式的方法,不过,我们现在无论是匹配还是重复都是针对单个字符进行操作,假如说我希望匹配一个以ab为循环的重复字符串应该如何去处理呢?
答案很简单,就是分组,分组我们通常使用()进行分组,例如匹配以ab为循环的字符串为:
^(ab)*
转义字符
有的时候,我们需要匹配的字符串中本身就含有正则表达式中的关键字符,我们则需要转义,例如我们需要匹配(ab)为循环的字符串:
^(\(ab\))*
反斜杠\就是我们的转义字符。不过对于C#中,字符串含有反斜杠会自动转义,为了避免这种情况,我们需要在字符串之前加上@或者将将转义字符转义,也就是\两个斜杠
条件或
有的时候,我们需要匹配的字符串可能是ab开头也有可能是cd开头,这个时候我们就使用条件语句处理,例如:
^(ab|cd)*
用逻辑或“|”进行处理。
区间匹配
有的时候,我们有可能是需要匹配比如说138-150之间所有数字开头的字符串,或者说A-F按字母表顺序内的字母开头,我们可以这样
^[138-150]*
^[A-F]*
反义
之前我们谈论的都是字符串中含有什么什么,现在我们可能需要匹配到字符串中不含有的字符,那么我们就需要使用反义,如下表
元字符 | 说明 |
---|---|
\W | 匹配不是字母、数字、下划线以及汉字 |
\S | 匹配不是空白符 |
\D | 匹配不是数字 |
\B | 匹配不是单词的开始或结束 |
[^x] | 匹配出了x以外的任意字符 |
贪婪模式与懒惰模式
贪婪
贪婪是当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符,这匹配方式叫做贪婪匹配。特性:一次性读入整个字符串进行匹配,每当不匹配就舍弃最右边一个字符,继续匹配,依次匹配和舍弃(这种匹配-舍弃的方式也叫做回溯),直到匹配成功或者把整个字符串舍弃完为止,因此它是一种最大化的数据返回,能多不会少。
事实上我们之前所谈论的重复限定符就是一种贪婪量词
举个例子例如我们需要匹配由2-5个数字组成的字符串,假设有这样一串数字51354 8454 1 568,使用^\d{2,5}进行匹配的结果是51354 8454 568,事实上对于这些而言,匹配两个就已经满足了,例如51已经满足该正则式,但是在贪婪匹配中,它会尽可能的多匹配,将整个字符串输出。
如果多个贪婪量词叠加在一起,如果字符串能满足他们各自最大程度的匹配时,就互不干扰,但如果不能满足时,会根据深度优先原则,也就是从左到右的每一个贪婪量词,优先最大数量的满足,剩余再分配下一个量词匹配。
懒惰
懒惰匹配:当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能少的字符,这匹配方式叫做懒惰匹配。特性:从左到右,从字符串的最左边开始匹配,每次试图不读入字符匹配,匹配成功,则完成匹配,否则读入一个字符再匹配,依此循环(读入字符、匹配)直到匹配成功或者把字符串的字符匹配完为止。
使用懒惰量词就是在贪婪量词后面中加?,对于之前的例子,他会匹配成51 35 84 54 56
拓展
零宽断言
零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。最好还是拿例子来说明吧: 断言用来声明一个应该为真的事实。正则表达式中只有当断言为真时才会继续进行匹配。
非常抽象而且笼统,对吧,事实上我也那么觉得,以上内容来自百度百科,因为我实在是很难解释这个东西,你可以理解为匹配不含正则结果的内容吧。
正向先行断言(正前瞻)
正前瞻的语法为:
//pattern为正则式
(?=pattern)
它用于匹配pattern表达式之前的内容,并不返回本身。感觉还是很奇怪对吧,举一个例子:今年我市GDP为5600亿元。假设你要将这句话中的5600取出来,你使用正前瞻的方式应该怎么做?
\d+(?=亿元)
正向后行断言(正后顾):
正后顾的语法为:
//pattern为正则式
(?<=pattern)
与正前瞻相反,他是返回pattern之后的内容,如果继续实现之前的内容,那么表达式就会变成
(<=今年我市GDP为)\d+
负向先行断言(负前瞻)
负前瞻的语法为:
//pattern为正则式
(?!pattern)
匹配非pattern表达式的前面内容,不返回本身。还是举之前的例子,我要找到5600亿元之前的字母,那么可以是
[A-Z]+(?!5600亿元)
负向后行断言(负后顾)
这个想必我不需要进行讲解各位也应当能思考出如何书写及使用了,他的语法类似的是:
//pattern为正则式
(?<!pattern)
作用当然是匹配非pattern之后的内容。
我在这里就举这几个例子,还有一些很好的使用手册你可以参考Microsoft Documents。
捕获与非捕获
捕获你可以理解为将表达式按组分配,例如你匹配一个电话010-8511561,010是区号,我们有可能利用正则式将它单独取出来。
数字编号捕获组
语法就是我们之前的分组,但是匹配这个电话号码的时候,他的表达式如果是
((\d{3})-(\d{7}))
那么他会分为三组,第一组是完整的电话,第二组是我们的区号,第三组是我们的电话号码。
命名编号捕获组
语法:
(?<name>exp)
这个name就是你自己自定义的,例如之前的我们可以写成
(?<quhao>\d{3})-(?<haoma>\d{7})
这样我们可以通过名称进行访问组内数据,具体的使用我会在后面进行讲解。
非捕获组
同之前相反,它用于表示不需要分组的数据
(?:exp)
例如我们不需要区号,那么正则式就变成了
(?:\d{3})-(\d{7})
反向引用
捕获会返回一个捕获组,这个分组是保存在内存中,不仅可以在正则表达式外部通过程序进行引用,也可以在正则表达式内部进行引用,这种引用方式就是反向引用。
同样的,根据捕获组命名规则,反向引用也有两种
1- 数字反向引用:\k或\number
2- 命名反向引用:\k或'name'
反向引用通常和捕获组是一同使用的,它的作用主要是用来查找一些重复的内容或者做替换指定字符。比如要查找一串字母"aabbbbgbddesddfiid"里成对的字母。
我们捋捋思路:
- 首先我们要有一个匹配字母的捕获组:(\w)
- 然后(\w)\1
这样就可以了,\1代表的是1分组,这样就是一个匹配成对字母的正则式了。
如何使用正则表达式
位于 System.Text.RegularExpressions 空间下的 Regex 可以对正则表达式进行处理。
Match
这是匹配结果的对象,内含这几个常用的属性及方法
- Value:匹配值
- Groups:分组
- Index:匹配值的第一个字符的索引
- Success:是否符合正则式
- NextMatch:下一个符合的匹配值
Regex.Matches
匹配多个符合的结果,返回一个MatchCollection数组,使用foreach并转换成Match对象进行访问.
- IsMatch:是否符合正则式
- Replace:替换匹配上正则式的字符串
- Split:按匹配上的字符串进行分割
- Match:返回第一个符合正则式的字符串
- Matches:返回所有符合的字符串
Reference
如果我的文章帮助了您,请您在github.NETCoreGuide项目帮我点一个star,在博客园中点一个关注和推荐。
.NETCore C# 中级篇2-4 一文带你完全弄懂正则表达式的更多相关文章
- .NETCore C# 中级篇2-6 Json与XML
.NETCoreCSharp 中级篇2-6 本节内容为Json和XML操作 简介 Json和XML文本是计算机网络通信中常见的文本格式,其中Json其实就是JavaScript中的数组与对象,体现了一 ...
- 【matlab 基础篇 03】一文带你全面了解 plot 绘图函数的使用(超详细+图文并茂)
快速入门matlab,系统地整理一遍,如何你和我一样是一个新手,那么此文很适合你: 文章目录 1 前言 2 plot 2.1 显示正弦波 2.2 修改颜色 2.3 修改点的形状 2.4 修改线的形状 ...
- 一文让你完全弄懂Stegosaurus
国内关于 Stegosaurus 的介绍少之又少,一般只是单纯的工具使用的讲解之类的,并且本人在学习过程中也是遇到了很多的问题,基于此种情况下写下此文,也是为我逝去的青春时光留个念想吧~ Stegos ...
- 面试都在问的微服务、服务治理、RPC、下一代微服务框架... 一文带你彻底搞懂!
文章每周持续更新,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 单体式应用程序 与微服务相对的另一个概念是传统的单体式应用程序( ...
- 面试都在问的「微服务」「RPC」「服务治理」「下一代微服务」一文带你彻底搞懂!
❝ 文章每周持续更新,各位的「三连」是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) ❞ 单体式应用程序 与微服务相对的另一个概念是传统的「单体式应用程 ...
- 一文带你快速搞懂动态字符串SDS,面试不再懵逼
目录 redis源码分析系列文章 前言 API使用 embstr和raw的区别 SDSHdr的定义 SDS具体逻辑图 SDS的优势 更快速的获取字符串长度 数据安全,不会截断 SDS关键代码分析 获取 ...
- 一文带大家彻底搞懂Hystrix!
前言? Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用 ...
- .NET Core C#中级篇2-5 常见实用类
.NETCore CSharp 中级篇2-5 本节内容为常见实用类和方法的使用 String.Format string.format方法是一个字符串格式化类,它里面的一些写法是对字符串进行指定格式的 ...
- 零基础学习openstack【完整中级篇】及openstack资源汇总
1.你是如何学习openstack的?2.你对openstack的组件了解多少?3.你认为openstack该如何学习? 一直想写关于openstack的方面的内容,今天终于整理完成.算是完成一桩心事 ...
随机推荐
- 数据结构与算法---线索化二叉树(Threaded BinaryTree)
先看一个问题 将数列 {1, 3, 6, 8, 10, 14 } 构建成一颗二叉树 问题分析: 当我们对上面的二叉树进行中序遍历时,数列为 {8, 3, 10, 1, 6, 14 } 但是 6, 8 ...
- 详解rel 属性及noflow
rel属性的意思是指: 当前页和指向页的关系. 而 rev 属性则指定从目标文档到源文档的关系.百度目前支持: rel='noflow'属性. rel属性的意思是指: 当前页和指向页的关系. < ...
- STM32F0_HAL库驱动描述——LL驱动程序概述
LL驱动概述 低层(LL)驱动器旨在提供快速轻量级的专家导向层,它比硬件更接近硬件: 与HAL相反,LLAPI不适用于优化访问不是关键功能的外设设备,或者需要大量软件配置和/或复杂的高级堆栈(如USB ...
- Python重试模块retrying
Python重试模块retrying 工作中经常碰到的问题就是,某个方法出现了异常,重试几次.循环重复一个方法是很常见的.比如爬虫中的获取代理,对获取失败的情况进行重试. 刚开始搜的几个博客讲的有点问 ...
- ListView在ScrollView中不显示全部的问题
在实际应用中,我们可能会遇到把ListView放到ScrollView中的情况,在这种情况下,ListView的滑动属性与ScrollView的滑动出现冲突,从而ListView只显示一项.这里提供一 ...
- CVE-2018-4407 漏洞复现POC
pip install scapy import scapy from scapy.all import * send(IP(dst="192.168.1.132",options ...
- python的socket模块
sk.bind(address) s.bind(address) 将套接字绑定到地址.address地址的格式取决于地址族.在AF_INET下,以元组(host,port)的形式表示地址. sk.li ...
- 博弈论基础之sg函数与nim
在算法竞赛中,博弈论题目往往是以icg.通俗的说就是两人交替操作,每步都各自合法,合法性与选手无关,只与游戏有关.往往我们需要求解在某一个游戏或几个游戏中的某个状态下,先手或后手谁会胜利的问题.就比如 ...
- Visual Studio 2015 WinForm应用程序打包教程
最近开发了一个小软件.由于需要打包.网上找了一些资料.然后整合了起来.希望对大家有所帮助.不全面请见谅. 本人开发工具用的是Visual Studio 2015 打包控件 InstallShield ...
- python load,loads,dumps,dump区别
json 模块提供了一种很简单的方式来编码和解码JSON数据. 其中两个主要的函数是 json.dumps()和 json.loads() , 要比其他序列化函数库如pickle的接口少得多. 下面演 ...