当前位置: 首页 > 编程日记 > 正文

c#正则表达式使用详解

正则表达式(Regular expressions)是一套语法匹配规则,各种语言,如Perl, .Net和Java都有其对应的共享的正则表达式类库。在.Net中,这个类库叫做Regex。
简单的说,Regex是从字符窗中查找匹配字符串的应用类。通过Regex,编程人员能够非常方便的从一段数据中提取自己所需要的数据信息。举一个简单的例子,让大家对Regex有个大概的了解:
Regex regex = new Regex(@"d+");
Match m = regex.Match("fox 9212gold");
Console.WriteLine(m.Value.ToString());
结果很明显,regex为我们找到了字符串”fox 9212gold”中的数字字符串,输出结果为”9212” .
对Regex有了一个基本的概念之后,我需要告诉你一个非常好的消息,那就是Regex可以为我们做的远不止这么一点点,他是一套功能非常强大语法匹配规则。当然,这里还有一个坏消息等着我们,那就是强大功能的语法规则自然需要大量纷繁复杂的keyword支持,这也为Regex的学习带来了极大的难度。想要真正掌握正则表达式,可不是几个sample能够全部揭示与说明的。

创建一个Regex对象
Regex的构造函数有三种,在这里就不讨论默认构造函数了。另外两个构造函数中,一个构造函数接收正则表达式字符串作为入参,另一个以正则表达式字符串和RegexOptions作为入参。如:
Regex regex = new Regex("w+$");
Regex regex = new Regex("s+", RegexOptions.IgnoreCase | RegexOptions.Multiline);
RegexOptions可以为我们提供一些特殊的帮助,比如IgnoreCase能够在匹配是忽略大小写,Multiline能够调整^和$的意义,改为匹配一行的开头和结尾。
上面我们构造了一个正则表达式,只不过我们还没有用它来做任何事情,马上我们就可以通过使用下面的几个方法,实现对字符串对象的操作了。
匹配字符串
Regex有两个获取匹配的方法Match()和Matches(),分别代表匹配一个,匹配多个结果。这里就用Matches来展示一下怎么使用Regex获取匹配字符串,并将其显示出来。
 
public static void showMatches(string expression, RegexOptions option, string ms)
{
Regex regex = new Regex(expression, option);
MatchCollection matches = regex.Matches(ms);
//show matches
Console.WriteLine("----------------------------------");
Console.WriteLine(" string: "{0}"  expression: "{1}"  match result is:", ms, expression);
foreach(Match m in matches)
{ Console.WriteLine("match string is: "{0}", length: {1}",m.Value.ToString(), m.Value.Length);
}
Console.WriteLine("matched count: {0}", matches.Count);
}
方法Matched通过比较入参字符串和正则表达式,找到所有符合的结果,并将结果作为MatchCollection传出来。这样,只要简单的遍历这个collection,就可以很快的获得所有的结果。

组的概念

当你获得这样的一个字符串”最后比分是:19/24”,你肯定希望有一个正则表达式,他不单能够找到形如 data1/data2的字符串,还应该能够直接把data1,data2作为单独的结果传送出来。否则你需要再对形如”19/24”的字符串进行分析,才能够顺利得到双方的比分。显然,正则表达式不会忽略这个问题,所以他增加了组的概念。你可以把一次搜索的结果分别放入不同的组中,并通过组名或者组的所以分别取得这些组的结果。比如上例,我们就可以用@”(\d+)/(\d+)”作为表达式。来看看结果吧:
 
Regex regex = new Regex(@"(d+)/(d+)");
MatchCollection matches = regex.Matches(@"最后比分是:19/24");
//show matches
Console.WriteLine("----------------------------------");
foreach(Match m in matches)
{
//Console.WriteLine("match string is: "{0}", length: {1}", // m.Value.ToString(), m.Value.Length);
foreach(string name in regex.GetGroupNames())
{
Console.WriteLine("  capture group "{0}" value is:"{1}"" , name, m.Groups[name].Value);
}
}
Console.WriteLine("matched count: {0}", matches.Count);
输出:
----------------------------------
capture group "0" value is:"19/24"
capture group "1" value is:"19"
capture group "2" value is:"24"
matched count: 1

现在清楚了吧,Regex对象把匹配的结果放入组0中。同时,匹配的组信息也放入了对应的组中。组的名称在默认的情况下,是从1开始依次增加的整数。0作为保留名称,专门用于指示匹配的整个字符串。既然有”默认情况”这样的概念,自然也就意味着用户可以自定义组的名称。方法很简单,在组的前面加上:?<name>就可以了。好了,现在把前面的正则表达式修改一下,换成@”(?<score1>\d+)/(?<score1>\d+)”,现在再看看结果:
----------------------------------
capture group "0" value is:"19/24"
capture group "score1" value is:"19"
capture group "score2" value is:"24"
matched count: 1

换成自己定义的名字了吧,哈哈!为了在今后的测试中,能够更加方便的看到所有结果,我们对前面介绍过的showMatches()做一点小小的调整。这样,如果在表达式中包含了组的定义,我们也可以在不需要修改任何代码的情况下,直接看到所有的组信息了,调整后的方法showMatchesPro()如下:

public static void showMatchesPro(string expression, RegexOptions option, string ms)
{
Regex regex = new Regex(expression, option);
MatchCollection matches = regex.Matches(ms);
//show matches
Console.WriteLine("----------------------------------");
Console.WriteLine(" string: "{0}"  expression: "{1}"  match result is:",ms, expression);
foreach(Match m in matches)
{
  foreach(string name in regex.GetGroupNames())
{
Console.WriteLine("  capture group "{0}" value is:"{1}"",name, m.Groups[name].Value);
}
}
Console.WriteLine("matched count: {0}", matches.Count);
// show group name
Console.WriteLine("group name count {0}", regex.GetGroupNames().Length);
foreach(string name in regex.GetGroupNames())
{
Console.WriteLine("group name :"{0}"", name);
}
}
替换字符串
Regex也提供了方便的匹配结果替换的功能。为了方便测试,我们也把他写成方法,代码如下:

public static string replaceMatch(string expression, RegexOptions option, string ms, string rep)
{
Regex regex = new Regex(expression, option);
string result = regex.Replace(ms, rep);
Console.WriteLine("----------------------------------");
Console.WriteLine("string: "{0}", expression:"{1}", replace by : "{2}"", ms, expression, rep);
Console.WriteLine("replace result string is: "{0}", length: {1}", result.ToString(), result.Length);
return result;
}

Regex.Replace通常接受两个string作为入参,第一个string为输入字符串。第二个字符串用来替代匹配字符串,它可以包含一些特殊字符串,用来代表特别转换。

特殊字符串 替换结果
$& 匹配的字符串,也可以用$0
$1, $2, . . . 匹配字符串中的对应组,用索引标示
${name} 匹配字符串中的对应组,用名称标示
$‘ 匹配位置之前的字符串
$’ 匹配位置之后的字符串
$$ 一个‘$’ 字符
$_ 输入字符串
$+ 匹配字符串的所有组中,最后一个组中的数据

是不是看了这么多怪型怪状的特殊字符串,有点头晕了?嗯,那就弄两个sample来看看结果吧!
Sample1:
replaceMatch(@"\d+", RegexOptions.None, "fef 12/21 df 33/14 727/1", "<<$&>>");
输出,所有数字型的数据都被替换成了<<data>>:
----------------------------------
string: "fef 12/21 df 33/14 727/1", expression:"\d+", replace by : "<<$&>>"
replace result string is: "fef <<12>>/<<21>> df <<33>>/<<14>> <<727>>/<<1>>",
length: 50

Sample2:
replaceMatch(@"(\d+)/(\d+)", RegexOptions.None, "fef 12/21 df 33/14 727/1", "$+");
输出,所有data1/data2匹配的数据,都被替换成了data2:
----------------------------------
string: "fef 12/21 df 33/14 727/1", expression:"(\d+)/(\d+)", replace by : "$+"
replace result string is: "fef 21 df 14 1", length: 16

怎么样,Regex的功能够丰富的吧!可是,也许你的需求不光这么简单,比如说,你要把”I have 200 dollars”中间的money加倍,怎么办?我晕倒,好像没有现成的东西可以用。没有关系,Regex还有更好的功能。它允许你自己定义转换公式。
 
using System.Text.RegularExpressions;
class RegularExpressions
{
static string CapText(Match m)
{
// Get the matched string.
string x = m.ToString();
// double this value
string result = (int.Parse(x) * 2).ToString();
return result;
}
static void Main()
{
string text = "i have 200 dollars";
string result = Regex.Replace(text, @"d+",new MatchEvaluator(RegularExpressions.CapText));
System.Console.WriteLine("result=[" + result + "]");
}
}
看看结果,太好了,我的钱真的变成了两倍!
但本文的目的是希望提供给大家一个方便好用的测试类,因此我们重载上面的repalceMatch方法,也允许自定义转换公式作为入参:

public static string replaceMatch(string expression, RegexOptions option, string ms,
MatchEvaluator evaluator)
{
Regex regex = new Regex(expression, option);
string result = regex.Replace(ms, evaluator);
Console.WriteLine("----------------------------------");
Console.WriteLine("string: "{0}", expression:"{1}", replace by a evaluator.", ms, expression);
Console.WriteLine("replace result string is: "{0}", length: {1}", result.ToString(), result.Length);
return result;
}
拆分字符串

Regex还提供了从匹配位置将字符串拆分的方法Split。这个方法同样具有多个重载,不过这些都不是重点,大家可以自己看文档。我们继续完成我们用于测试的方法:
public static void splitMatch(string expression, RegexOptions option, string ms)
{
Regex regex = new Regex(expression, option);
string[] result = regex.Split(ms);
Console.WriteLine("----------------------------------");
Console.WriteLine("string: "{0}", expression: "{1}", split result is:", ms, expression);
foreach(string m in result)
{
Console.WriteLine("splited string is: "{0}", length: {1}",m.ToString(), m.Length);
}
Console.WriteLine("splited count: {0}", result.Length);
}
代码简单,不多做解释。直接来一个smaple看看结果:
splitMatch(@"/",RegexOptions.None, "2004/4/25");
输出:
----------------------------------
string: "2004/4/25", expression: "/", split result is:
splited string is: "2004", length: 4
splited string is: "4", length: 1
splited string is: "25", length: 2
splited count: 3

这个文章的目的很简单:介绍Regex的几个主要功能(匹配、替换和拆分),并提供几个简单方便的测试函数。让你能够测试你对正则表达式的理解是否准确。

比如想要确认^$的作用,你可以放入这样的(input, expression)数据:
(“123”, “^\d+$”) (“123aaa456”, “^\d+”) (“123aaa456”, “123&”)

确认\d, \s, \w, \W的作用,可以这样测试:
(“123abc gc 456”, “\d+”)(“123abc gc 456”, “\s+”)
(“123abc gc 456”, “\w+”)(“123abc gc 456”, “\W+”)

比较? + *之间的区别可以用这样的数据:
(“a123 abcd”, “a\d?”) (“a123 abcd”, “a\d+”) (“a123 abcd”, “a\d*”)

转载于:https://www.cnblogs.com/jxnclyk/archive/2010/09/03/1816773.html

相关文章:

软件安装(ubuntu) --Linux基础编程

Ubuntu&#xff1a;一个以桌面应用为主的开源GNU/Linux操作系统 1、在线安装&#xff08;Ubuntu Example&#xff09; 【安装】&#xff1a;sudo apt-get install 安装包的名字&#xff0c;或者&#xff1a;sudo apt install 安装包的名字&#xff08;16.04及以上版本&#xff…

Springboot结合 framework 加载静资源 出现404 问题解决 记录

<!- 在HTML页面加入这样--><#assign ctxrequest.contextPath /> 在引入的静态资源路径上 添加以下内容

studyLink

http://order.csdn.net/myorder/detail?id850343 csdn 转载于:https://www.cnblogs.com/zhujiasheng/p/8010861.html

CCNA的一个综合实验(经典)

【背景描述】 该企业的具体环境如下&#xff1a; 1、企业具有2个办公地点&#xff0c;且相距较远&#xff0c;公司总共大约有200台主机。 2、A办公地点具有的部门较多&#xff0c;例如业务部、财务部、综合部等&#xff0c;为主要的办公场所&#xff0c;因此这部分的交换网络对…

关于EF中批量添加的个人探索

实际的测试代码和数据记录&#xff0c;还有最终的总结都在下面&#xff1a; /// <summary>/// 这种做法&#xff0c;不用了说了&#xff0c;每次遍历都会打开一次db链接&#xff0c;然后执行insert操作&#xff1b;/// </summary>static void CreateBluckInsertDat…

HDOJ 1157 HDU 1157 Who's in the Middle ACM 1157 IN HDU

MiYu原创, 转帖请注明 : 转载自 ______________白白の屋 题目地址:http://acm.hdu.edu.cn/showproblem.php?pid1157 题目描述:Whos in the MiddleTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2451 Accep…

Keras使用多个GPU并行

model Model(inputs[v_i, v_j], outputsoutput_list) model multi_gpu_model(model,4) model.compile(....) 主要就是第二句话中的 multi_gpu_model函数&#xff0c;会把数据和模型分到多个gpu上执行有个坑&#xff0c;就是整个程序导入keras时要么全部from keras import ...…

使用JackJSON 流式API 创建JSON串【学习记录】

教程网址&#xff1a;Jackson流式API 目标JSON串 原始JSON串 核心代码 思路&#xff1a;先将原始JSON串生成对应的对象&#xff0c;获取到其数据 package com.run.runlpwebdemo.utils;import java.io.IOException; import java.io.StringWriter; import java.util.List;impo…

Eclipse插件安装

clispe想必大家都很熟悉了&#xff0c;一般来说&#xff0c;eclipse 插件都是安装在plugins目录 下。不过这样一来&#xff0c;当安装了许多插件之后&#xff0c;eclipse变的很大&#xff0c;最主要的是不便 于更新和管理众多插件。用links 方式安装eclipse插件&#xff0c;可以…

linux 命令之文件读取,head, tail, tailf, sed

head 看文件的前100行head -100 filename tail/tailf查看文件的后100行tail -100 filename 或 tail -n 100 filename tailf filename tail -f filename sed sed -n 100,200p filename 这样你就可以只查看文件的第100行到第200行。 转载于:https://www.cnblogs.com/xiaoniu-…

软件使用[19]

1 -- 服务自动的原理2 -- 命令chkconfig使用方法chkconfig是Linux系统中基于命令行的服务管理工具&#xff0c;其用途是启用和禁用系统服务。 chkconfig --list [name] chkconfig --add name chkconfig --del name chkconfig [--level levels] name chkconfig [--level le…

ORA-01747: user.table.column, table.column 或列说明无效 异常解决方法总结

1.sql 拼接错误 比如多了个逗号&#xff0c;少了个引号什么的&#xff0c;大部分其实都是这个问题&#xff0c;还是多细心&#xff0c;复制粘贴的时候多看看。 2.sql语句中使用了 Oracle 声明的关键字 --查询数据库关键字select * from v$reserved_words;----查询表中是否有关键…

SpringBoot 获取 application.properties 文件中的内容方法 【学习记录】

1 . Value注解来获取配置的值 2. ConfigurationProperties注解

安装swoole

php需要安装swoole扩展 swoole4.3.2 cd /usr/local/src/wget https://pecl.php.net/get/swoole-4.3.2.tgztar -zxvf swoole-4.3.2.tgzmv swoole-4.3.2 swoolecd swoole/usr/local/php/bin/phpize# 增加php配置./configure --enable-openssl --enable-swoole --enable-http2 --e…

layUI 学习记录

1 点击导航栏跳转页面 <!DOCTYPE html> <html> <head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width, initial-scale1, maximum-scale1"><title>layout 后台大布局 - Layui</ti…

分享个网盘,个人觉得很不错!

金山网盘&#xff1a;http://k.wps.cn 可以在电脑上虚拟一个盘&#xff0c;你要上传下载删除文件&#xff0c;可以直接在本地电脑上操作&#xff0c;就像用自己硬盘的一个分区或是U盘一样&#xff0c;操作方便&#xff0c;但速度肯定没硬盘U盘快了&#xff0c;真正速度取决于你…

JSP 学习笔记 3

八jsp 九个内置对象1.内置对象的描述这就个内置对象都是servlet API的类或者接口的实例。JSP把他们都初始化了。2.九个内置对象分别是l application: javax.servlet.ServletContext的实例&#xff0c;代表JSP所属WEB应用本身&#xff0c;用于JSP叶面之间&#xff0c;或…

空间新闻模块CSS

#mod_10024 { /* 国内新闻模块 */ } #mod_10024 .modtl { /* 题头左 */ } #mod_10024 .modtc { /* 题头中 */ } #mod_10024 .modtr { /* 题头右 */ } #mod_10024 .modtit { /* 模块标题 */ } #mod_10024 a.modact img { /* "编辑图标" */ } #mod_10024 a.modact,#mod…

Cordova入门系列(三)Cordova插件调用

上一章我们介绍了cordova android项目是如何运行的&#xff0c;这一章我们介绍cordova的核心内容&#xff0c;插件的调用。演示一个例子&#xff0c;通过cordova插件&#xff0c;去调用摄像头。 一、插件的安装以及基本信息&#xff1a; 我们先在项目中安装调用摄像头的插件cor…

LVS 介绍 原理

一、 LVS简介 LVS是Linux Virtual Server的简称&#xff0c;也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项目&#xff0c;它的官方站点是www.linuxvirtualserver.org&#xff08;版本很久不更新了&#xff09;。 现在LVS已经是 Linux标准内核的一部分…

腾讯云 短信服务 【学习记录 】

github 链接 https://github.com/qcloudsms/qcloudsms_java/tree/master maven 要使用 qcloudsms_java 功能&#xff0c;需要在 pom.xml 中添加如下依赖&#xff0c; <dependency><groupId>com.github.qcloudsms</groupId><artifactId>qcloudsms<…

Coolite Toolkit学习笔记六:常用控件Accordion、ToolBar、ToolTip

一、Accordion控件 Accordion的功能非常适用&#xff0c;使用很简单&#xff0c;轻轻松松的就可以构建一个可折叠的界面展示应用效果。相信大多数做ASP.NET开发的朋友都使用过ASP.NET AJAX Control Toolkit&#xff0c;它里面也提供有Accordion控件&#xff0c;详细可以查…

与ObjectDataSource共舞

4&#xff0c;ORM组件XCode&#xff08;与ObjectDataSource共舞&#xff09; XCode为了能更方便的解决大部分问题&#xff0c;不得不“屈身”于ObjectDataSource。 先上一个经典例子&#xff08;ObjectDataSourceGridView&#xff09;&#xff08;ObjectDataSource&#xff09;…

2.4 Go语言基础之切片

本文主要介绍Go语言中切片&#xff08;slice&#xff09;及它的基本使用。 一、引子 因为数组的长度是固定的并且数组长度属于类型的一部分&#xff0c;所以数组有很多的局限性。 例如&#xff1a; func arraySum(x [3]int) int{sum : 0for _, v : range x{sum sum v}return …

java 文件下载 【学习记录】

工具类 public static Boolean downloadExcelFile(HttpServletResponse response, String fileName) {OutputStream output;File file new File(fileName);if (file.exists()) {try {FileInputStream fileInputStream new FileInputStream(file);BufferedInputStream buffe…

[UI自动化]:控制浏览器操作

控制浏览器窗口大小 . PC端执行自动化测试脚本大多的情况下是希望浏览器在全屏幕模式下执行&#xff0c;那么可以使用maximize_window()方法使打开的浏览器全屏显示 控制浏览器后退、前进 在使用浏览器浏览网页时&#xff0c;浏览器提供了后退和前进按钮&#xff0c;可以方便地…

在项目中使用Google Closure Compiler

现在的Web项目总是离不开大量JavaScript&#xff0c;而JS文件的体积也越来越大&#xff0c;也越来越影响页面的感知性能&#xff08;Perceived Performance&#xff09;。因此&#xff0c;我们会对JS文件进行压缩&#xff0c;一方面是使用Gzip&#xff0c;而另一方面则是去除JS…

文件服务器共享目录设置(二)

三、 设置磁盘配额及文件屏蔽 为了防止用户无限制的上传文件&#xff0c;或上传病毒木马等文件&#xff0c;还需要进一步加强安全设置。用磁盘配额来管理用户的文件夹空间&#xff0c;用文件屏蔽来阻止用户上传有风险的文件。 在win2003中&#xff0c;磁盘配额只能…

Codeforces 894.D Ralph And His Tour in Binary Country

D. Ralph And His Tour in Binary Countrytime limit per test2.5 secondsmemory limit per test512 megabytesinputstandard inputoutputstandard outputRalph is in the Binary Country. The Binary Country consists of n cities and (n - 1) bidirectional roads connect…

linux下获取系统时间 和 时间偏移

获取linux时间 并计算时间偏移 void getSystemTimer(void){#if 0 char *wdate[]{"Sun","Mon","Tue","Wed","Thu","Fri","Sat"} ; time_t timep; struct tm *p; time(&timep); pgmtime(&timep)…