C#正则表达式整理备忘


C#正则表达式整理备忘

(1)“@”符号
符下两ows表研究室的火热,当晨在“@”虽然并非C#正则表达式的“成员”,但是它经常与C#正则表达式出双入对。“@”表示,跟在它后面的字符串是个“逐字字符串”,不是很好理解,举个例子,以下两个声明是等效的:
string x="D:\\My Huang\\My Doc";
string y = @"D:\My Huang\My Doc";
事实上,如果按如下声明,C#将会报错,因为“\”在C#中用于实现转义,如“\n”换行:
string x = "D:\My Huang\My Doc";

(2)基本的语法字符。
\d  0-9的数字
\D  \d的补集(以所以字符为全集,下同),即所有非数字的字符
\w  单词字符,指大小写字母、0-9的数字、下划线
\W  \w的补集
\s  空白字符,包括换行符\n、回车符\r、制表符\t、垂直制表符\v、换页符\f
\S  \s的补集
.  除换行符\n外的任意字符
[…]  匹配[]内所列出的所有字符
[^…]  匹配非[]内所列出的字符
下面提供一些简单的示例:

 

C# Code:

string i = "\n";
string m = "3";
Regex r = new Regex(@"\D");
//同Regex r = new Regex("\\D");
//r.IsMatch(i)结果:true
//r.IsMatch(m)结果:false

string i = "%";
string m = "3";
Regex r = new Regex("[a-z0-9]");
//匹配小写字母或数字字符
//r.IsMatch(i)结果:false
//r.IsMatch(m)结果:true




(3)定位字符
“定位字符”所代表的是一个虚的字符,它代表一个位置,你也可以直观地认为“定位字符”所代表的是某个字符与字符间的那个微小间隙。
^  表示其后的字符必须位于字符串的开始处
$  表示其前面的字符必须位于字符串的结束处
\b  匹配一个单词的边界
\B  匹配一个非单词的边界
另外,还包括:\A  前面的字符必须位于字符处的开始处,\z  前面的字符必须位于字符串的结束处,\Z  前面的字符必须位于字符串的结束处,或者位于换行符前
下面提供一些简单的示例:

C# Code:


string i = "Live for nothing,die for something";
Regex r1 = new Regex("^Live for nothing,die for something$");
//r1.IsMatch(i) true
Regex r2 = new Regex("^Live for nothing,die for some$");
//r2.IsMatch(i) false
Regex r3 = new Regex("^Live for nothing,die for some");
//r3.IsMatch(i) true

string i = @"Live for nothing,
die for something";//多行
Regex r1 = new Regex("^Live for nothing,die for something$");
Console.WriteLine("r1 match count:" r1.Matches(i).Count);//0
Regex r2 = new Regex("^Live for nothing,die for something$", RegexOptions.Multiline);
Console.WriteLine("r2 match count:" r2.Matches(i).Count);//0
Regex r3 = new Regex("^Live for nothing,\r\ndie for something$");
Console.WriteLine("r3 match count:" r3.Matches(i).Count);//1
Regex r4 = new Regex("^Live for nothing,$");
Console.WriteLine("r4 match count:" r4.Matches(i).Count);//0
Regex r5 = new Regex("^Live for nothing,$", RegexOptions.Multiline);
Console.WriteLine("r5 match count:" r5.Matches(i).Count);//0
Regex r6 = new Regex("^Live for nothing,\r\n$");
Console.WriteLine("r6 match count:" r6.Matches(i).Count);//0
Regex r7 = new Regex("^Live for nothing,\r\n$", RegexOptions.Multiline);
Console.WriteLine("r7 match count:" r7.Matches(i).Count);//0
Regex r8 = new Regex("^Live for nothing,\r$");
Console.WriteLine("r8 match count:" r8.Matches(i).Count);//0
Regex r9 = new Regex("^Live for nothing,\r$", RegexOptions.Multiline);
Console.WriteLine("r9 match count:" r9.Matches(i).Count);//1
Regex r10 = new Regex("^die for something$");
Console.WriteLine("r10 match count:" r10.Matches(i).Count);//0
Regex r11 = new Regex("^die for something$", RegexOptions.Multiline);
Console.WriteLine("r11 match count:" r11.Matches(i).Count);//1
Regex r12 = new Regex("^");
Console.WriteLine("r12 match count:" r12.Matches(i).Count);//1
Regex r13 = new Regex("$");
Console.WriteLine("r13 match count:" r13.Matches(i).Count);//1
Regex r14 = new Regex("^", RegexOptions.Multiline);
Console.WriteLine("r14 match count:" r14.Matches(i).Count);//2
Regex r15 = new Regex("$", RegexOptions.Multiline);
Console.WriteLine("r15 match count:" r15.Matches(i).Count);//2
Regex r16 = new Regex("^Live for nothing,\r$\n^die for something$", RegexOptions.Multiline);
Console.WriteLine("r16 match count:" r16.Matches(i).Count);//1
//对于一个多行字符串,在设置了Multiline选项之后,^和$将出现多次匹配。

string i = "Live for nothing,die for something";
string m = "Live for nothing,die for some thing";
Regex r1 = new Regex(@"\bthing\b");
Console.WriteLine("r1 match count:" r1.Matches(i).Count);//0
Regex r2 = new Regex(@"thing\b");
Console.WriteLine("r2 match count:" r2.Matches(i).Count);//2
Regex r3 = new Regex(@"\bthing\b");
Console.WriteLine("r3 match count:" r3.Matches(m).Count);//1
Regex r4 = new Regex(@"\bfor something\b");
Console.WriteLine("r4 match count:" r4.Matches(i).Count);//1
//\b通常用于约束一个完整的单词







 (4)重复描述字符
“重复描述字符”是体现C#正则表达式“很好很强大”的地方之一:
{n}  匹配前面的字符n次
{n,}  匹配前面的字符n次或多于n次
{n,m}  匹配前面的字符n到m次
?  匹配前面的字符0或1次
+  匹配前面的字符1次或多于1次
*  匹配前面的字符0次或式于0次
以下提供一些简单的示例:

Code

C# Code:

string x = "1024";
string y = " 1024";
string z = "1,024";
string a = "1";
string b="-1024";
string c = "10000";
Regex r = new Regex(@"^\ ?[1-9],?\d{3}$");
Console.WriteLine("x match count:" r.Matches(x).Count);//1
Console.WriteLine("y match count:" r.Matches(y).Count);//1
Console.WriteLine("z match count:" r.Matches(z).Count);//1
Console.WriteLine("a match count:" r.Matches(a).Count);//0
Console.WriteLine("b match count:" r.Matches(b).Count);//0
Console.WriteLine("c match count:" r.Matches(c).Count);//0
//匹配1000到9999的整数。





 



 (5)择一匹配
C#正则表达式中的 (|) 符号似乎没有一个专门的称谓,姑且称之为“择一匹配”吧。事实上,像[a-z]也是一种择一匹配,只不过它只能匹配单个字符,而(|)则提供了更大的范围,(ab|xy)表示匹配ab或匹配xy。注意“|”与“()”在此是一个整体。下面提供一些简单的示例:

Code

C# Code:


string x = "0";
string y = "0.23";
string z = "100";
string a = "100.01";
string b = "9.9";
string c = "99.9";
string d = "99.";
string e = "00.1";
Regex r = new Regex(@"^\ ?((100(.0 )*)|([1-9]?[0-9])(\.\d )*)$");
Console.WriteLine("x match count:" r.Matches(x).Count);//1
Console.WriteLine("y match count:" r.Matches(y).Count);//1
Console.WriteLine("z match count:" r.Matches(z).Count);//1
Console.WriteLine("a match count:" r.Matches(a).Count);//0
Console.WriteLine("b match count:" r.Matches(b).Count);//1
Console.WriteLine("c match count:" r.Matches(c).Count);//1
Console.WriteLine("d match count:" r.Matches(d).Count);//0
Console.WriteLine("e match count:" r.Matches(e).Count);//0





 

//匹配0到100的数。最外层的括号内包含两部分“(100(.0+)*)”,“([1-9]?[0-9])(\.\d+)*”,这两部分是“OR”的关系,即正则表达式引擎会先尝试匹配100,如果失败,则尝试匹配后一个表达式(表示[0,100)范围中的数字)。


(6)特殊字符的匹配
下面提供一些简单的示例:

Code

C# Code:


string x = "\\";
Regex r1 = new Regex("^\\\\$");
Console.WriteLine("r1 match count:" r1.Matches(x).Count);//1
Regex r2 = new Regex(@"^\\$");
Console.WriteLine("r2 match count:" r2.Matches(x).Count);//1
Regex r3 = new Regex("^\\$");
Console.WriteLine("r3 match count:" r3.Matches(x).Count);//0
//匹配“\”

string x = "\"";
Regex r1 = new Regex("^\"$");
Console.WriteLine("r1 match count:" r1.Matches(x).Count);//1
Regex r2 = new Regex(@"^""$");
Console.WriteLine("r2 match count:" r2.Matches(x).Count);//1
//匹配双引号





 



 

 (7)组与非捕获组
以下提供一些简单的示例:

Code

C# Code:


string x = "Live for nothing,die for something";
string y = "Live for nothing,die for somebody";
Regex r = new Regex(@"^Live ([a-z]{3}) no([a-z]{5}),die \1 some\2$");
Console.WriteLine("x match count:" r.Matches(x).Count);//1
Console.WriteLine("y match count:" r.Matches(y).Count);//0
//正则表达式引擎会记忆“()”中匹配到的内容,作为一个“组”,并且可以通过索引的方式进行引用。表达式中的“\1”,用于反向引用表达式中出现的第一个组,即粗体标识的第一个括号内容,“\2”则依此类推。

string x = "Live for nothing,die for something";
Regex r = new Regex(@"^Live for no([a-z]{5}),die for some\1$");
if (r.IsMatch(x))
{
   Console.WriteLine("group1 value:" r.Match(x).Groups[1].Value);//输出:thing
}
//获取组中的内容。注意,此处是Groups[1],因为Groups[0]是整个匹配的字符串,即整个变量x的内容。

string x = "Live for nothing,die for something";
Regex r = new Regex(@"^Live for no(?<g1>[a-z]{5}),die for some\1$");
if (r.IsMatch(x))
{
   Console.WriteLine("group1 value:" r.Match(x).Groups["g1"].Value);//输出:thing
}
//可根据组名进行索引。使用以下格式为标识一个组的名称(?<groupname>…)。

string x = "Live for nothing nothing";
Regex r = new Regex(@"([a-z] ) \1");
if (r.IsMatch(x))
{
   x = r.Replace(x, "$1");
   Console.WriteLine("var x:" x);//输出:Live for nothing
}
//删除原字符串中重复出现的“nothing”。在表达式之外,使用“$1”来引用第一个组,下面则是通过组名来引用:
string x = "Live for nothing nothing";
Regex r = new Regex(@"(?<g1>[a-z] ) \1");
if (r.IsMatch(x))
{
   x = r.Replace(x, "${g1}");
   Console.WriteLine("var x:" x);//输出:Live for nothing
}

string x = "Live for nothing";
Regex r = new Regex(@"^Live for no(?:[a-z]{5})$");
if (r.IsMatch(x))
{
   Console.WriteLine("group1 value:" r.Match(x).Groups[1].Value);//输出:(空)
}
//在组前加上“?:”表示这是个“非捕获组”,即引擎将不保存该组的内容。







 


(8)贪婪与非贪婪
正则表达式的引擎是贪婪,只要模式允许,它将匹配尽可能多的字符。通过在“重复描述字符”(*,+)后面添加“?”,可以将匹配模式改成非贪婪。请看以下示例:

Code

C# Code:


string x = "Live for nothing,die for something";
Regex r1 = new Regex(@".*thing");
if (r1.IsMatch(x))
{
   Console.WriteLine("match:" r1.Match(x).Value);//输出:Live for nothing,die for something
}
Regex r2 = new Regex(@".*?thing");
if (r2.IsMatch(x))
{
   Console.WriteLine("match:" r2.Match(x).Value);//输出:Live for nothing
}





 



(9)回溯与非回溯
使用“(?>…)”方式进行非回溯声明。由于正则表达式引擎的贪婪特性,导致它在某些情况下,将进行回溯以获得匹配,请看下面的示例:

Code

C# Code:


string x = "Live for nothing,die for something";
Regex r1 = new Regex(@".*thing,");
if (r1.IsMatch(x))
{
   Console.WriteLine("match:" r1.Match(x).Value);//输出:Live for nothing,
}
Regex r2 = new Regex(@"(?>.*)thing,");
if (r2.IsMatch(x))//不匹配
{
   Console.WriteLine("match:" r2.Match(x).Value);
}





 



//在r1中,“.*”由于其贪婪特性,将一直匹配到字符串的最后,随后匹配“thing”,但在匹配“,”时失败,此时引擎将回溯,并在“thing,”处匹配成功。
在r2中,由于强制非回溯,所以整个表达式匹配失败。

(10)正向预搜索、反向预搜索
正向预搜索声明格式:正声明 “(?=…)”,负声明 “(?!...)” ,声明本身不作为最终匹配结果的一部分,请看下面的示例:

Code

string x = "1024 used 2048 free";
Regex r1 = new Regex(@"\d{4}(?= used)");
if (r1.Matches(x).Count==1)
{
    Console.WriteLine("r1 match:" + r1.Match(x).Value);//输出:1024
}
Regex r2 = new Regex(@"\d{4}(?! used)");
if (r2.Matches(x).Count==1)
{
    Console.WriteLine("r2 match:" + r2.Match(x).Value); //输出:2048
}
//r1中的正声明表示必须保证在四位数字的后面必须紧跟着“ used”,r2中的负声明表示四位数字之后不能跟有“ used”。

反向预搜索声明格式:正声明“(?<=)”,负声明“(?<!)”,声明本身不作为最终匹配结果的一部分,请看下面的示例:

Code

C# Code:


string x = "used:1024 free:2048";
Regex r1 = new Regex(@"(?<=used:)\d{4}");
if (r1.Matches(x).Count==1)
{
   Console.WriteLine("r1 match:" r1.Match(x).Value);//输出:1024
}
Regex r2 = new Regex(@"(?<!used:)\d{4}");
if (r2.Matches(x).Count==1)
{
   Console.WriteLine("r2 match:" r2.Match(x).Value);//输出:2048
}





 



//r1中的反向正声明表示在4位数字之前必须紧跟着“used:”,r2中的反向负声明表示在4位数字之前必须紧跟着除“used:”之外的字符串。

(11)十六进制字符范围
正则表达式中,可以使用 "\xXX" 和 "\uXXXX" 表示一个字符("X" 表示一个十六进制数)形式字符范围:
\xXX       编号在 0到255 范围的字符,比如:空格可以使用 "\x20" 表示。
\uXXXX   任何字符可以使用 "\u" 再加上其编号的4位十六进制数表示,比如:汉字可以使用“[\u4e00-\u9fa5]”表示。


(12)对[0,100]的比较完备的匹配
下面是一个比较综合的示例,对于匹配[0,100],需要特殊考虑的地方包括
*00合法,00.合法,00.00合法,001.100合法
*空字符串不合法,仅小数点不合法,大于100不合法
*数值是可带后缀的,如“1.07f”表示该值为一个float类型(未考虑)

Code

C# Code:


Regex r = new Regex(@"^\ ?0*(?:100(\.0*)?|(\d{0,2}(?=\.\d)|\d{1,2}(?=($|\.$)))(\.\d*)?)$");
string x = "";
while (true)
{
   x = Console.ReadLine();
   if (x != "exit")
   {
      if (r.IsMatch(x))
      {
         Console.WriteLine(x " succeed!");
      }
      else
      {
         Console.WriteLine(x " failed!");
      }
   }
   else
   {
      break;
   }
}





 



(13)精确匹配有时候是困难的
有些需求要做到精确匹配比较困难,例如:日期、Url、Email地址等,其中一些你甚至需要研究一些专门的文档写出精确完备的表达式,对于这种情况,只能退而求其次,保证比较精确的匹配。例如对于日期,可以基于应用系统的实际情况考虑一段较短的时间,或者对于像Email的匹配,可以只考虑最常见的形式。

本文来源:
版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
C/S框架网
上一篇:C#中将数据插入到Excel表中
下一篇:C#开发自定义控件-设置显示工具箱中的图标
评论列表

发表评论

评论内容
昵称:
关联文章

C#表达式整理
C#.NET 手机号码表达式验证
C#表达式判断URL是否正确
C#使用表达式判断手机号码
C#.NET IP地址表达式验证
C#表达式替换SQL单引号中间的空格
C#.NET 身份证号码格式表达式验证
C#表达式查找或替换指定字符串(标识)范围的内容
C#表达式判断url是否网络路径(http/ftp/https三种协议)
C#使用表达式移除所有的Html标记,返回纯文本
C#使用表达式替换或去掉半角标点符号
C# 从html中通过找到IP地址信息(只支持ipv4地址)
C#的Expression表达式使用方法
C# Lambda表达式=>符号的使用
正在整理C/S结构系统框架 - 标准版(ADO Direct) Ver:2.2
C#+EF 使用SQL计算表达式
VS表达式包含未定义的函数调用IsNullOrEmpty|C/S框架网
尝试释放在使用的RCW,活动线程或其他线程上在使用该RCW
变更版本Bug,请更
菜单定义,把原来权限去掉后保存,若再修改无法勾选回去

热门标签
.NET5 .NET6 .NET7 APP Auth-软件授权注册系统 Axios B/S B/S开发框架 Bug Bug记录 C#加密解密 C#源码 C/S CHATGPT CMS系统 CodeGenerator CSFramework.DB CSFramework.EF CSFrameworkV1学习版 CSFrameworkV2标准版 CSFrameworkV3高级版 CSFrameworkV4企业版 CSFrameworkV5旗舰版 CSFrameworkV6.0 DAL数据访问层 Database datalock DbFramework Demo教学 Demo下载 DevExpress教程 DOM EF框架 Element-UI EntityFramework ERP ES6 Excel FastReport GIT HR IDatabase IIS JavaScript LINQ MES MiniFramework MIS NavBarControl Node.JS NPM OMS ORM PaaS POS Promise API Redis SAP SEO SQL SQLConnector TMS系统 Token令牌 VS2022 VSCode VUE WCF WebApi WebApi NETCore WebApi框架 WEB开发框架 Windows服务 Winform 开发框架 Winform 开发平台 WinFramework Workflow工作流 Workflow流程引擎 版本区别 报表 踩坑日记 操作手册 代码生成器 迭代开发记录 基础资料窗体 架构设计 角色权限 开发sce 开发技巧 开发教程 开发框架 开发平台 开发指南 客户案例 快速搭站系统 快速开发平台 秘钥 密钥 权限设计 软件报价 软件测试报告 软件简介 软件开发框架 软件开发平台 软件开发文档 软件体系架构 软件下载 软著证书 三层架构 设计模式 生成代码 实用小技巧 收钱音箱 数据锁 数据同步 微信小程序 未解决问题 文档下载 喜鹊ERP 喜鹊软件 系统对接 详细设计说明书 行政区域数据库 需求分析 疑难杂症 蝇量级框架 蝇量框架 用户管理 用户开发手册 用户控件 在线支付 纸箱ERP 智能语音收款机 自定义窗体 自定义组件 自动升级程序