- 浏览: 297655 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
全站唯一是我么:
请问下该功能的jdk版本是1.4的么,还是以上的?
Java实现给图片添加水印 -
Janne:
请问,你解决这问题没?是怎么回事?我今天也遇到了,没解决
myeclipse6.5中使用jax-ws启动tomcat报错问题 -
xuedong:
studypi 写道你是怎么和新浪的技术联系的?能告诉一下我吗 ...
新浪微博第三方接口调用学习 -
studypi:
你是怎么和新浪的技术联系的?能告诉一下我吗,谢谢
新浪微博第三方接口调用学习 -
dove19900520:
有用,呵呵
IE,Firefox都不放弃(兼容性问题总结)
1 概述
一般的正则替换,只能对匹配的子串做简单的处理,且只能是做string类型的处理之后,作为替换文本替换匹配子串,可以实现的功能比较有限。.NET的Replace()方法中的replacement参数,不仅可以是字符串,还可以是委托(delegate),在每次匹配成功时,都会调用委托方法,对匹配的子串进行处理之后,再作为替换文本返回,匹配子串使用委托方法,可以做任意复杂的处理,因此这种替换功能非常强大。
委托的类型可以是MatchEvaluator,也可以是匿名方法,在每次匹配成功时调用。委托方法传入参数是Match对象,返回类型是string,即正则表达式在每次匹配成功时,会得到一个Match对象,作为参数传给委托方法,做一定处理后,返回替换文本,替换匹配到的子串。
2 委托和匿名方法
在正则替换中使用的委托,一般有两种方式,显式声明的委托和匿名方法。下面以实例说明两种方式的使用方法。委托和匿名方法的区别和各自的特点不在这里介绍,请参考相关文献或文章。
2.1 委托
举例:
源字符串: a=10, b=20, c=30
需求:将字符串中的数字加100。
//委托方法
private string regReplace(Match m)
{
return (Convert.ToInt32(m.Value) + 100).ToString();
}
//声明一个MatchEvaluator类型委托
MatchEvaluator me = new MatchEvaluator(regReplace);
//正则替换应用
string test = "a=10, b=20, c=30";
Regex reg = new Regex(@"(?i)(?<=[a-z]=)/d+");
string result = reg.Replace(test, me);
richTextBox2.Text = result;
/*--------输出--------
a=110, b=120, c=130
*/
2.2 匿名方法
事实上,对于以上这种简单的需求,不需要显式的声明委托,直接使用匿名方法即可,
string test = "a=10, b=20, c=30";
Regex reg = new Regex(@"(?i)(?<=[a-z]=)/d+");
string result = reg.Replace(test, delegate(Match m) { return (Convert.ToInt32(m.Value) + 100).ToString(); });
richTextBox2.Text = result;
/*--------输出--------
a=110, b=120, c=130
*/
3 正则中委托的典型应用场景
一个涉及到替换的需求,首先要进行分析,是否能够通过一个正则表达式进行直接替换,如果不可以,那就要借助委托了。接下来就要找出可在委托方法中进行处理的子串的规律,剩下的就是委托方法中最基本的字符串处理了。
正则中委托的典型应用场景一般可归纳为以下几种:
1、替换子串需进行非string类型的处理,如计算等;
2、替换子串需经过条件或逻辑判断来决定处理方式;
3、多种条件组合的替换。
以上分类方式或许有重叠的地方,但是都比较有代表性,所以单独进行举例说明。
3.1 非string类型处理
替换子串非string类型处理,最典型的就是以上举例中的计算。还有比较典型的就是涉及计数的问题。
举例:
源字符串:<a href="http://www.sina.com.cn/">新浪 </a> <a href="http://www.sohu.com/">搜狐 </a> <a href="http://www.qq.com/">腾讯QQ </a> <a href="http://www.163.com/">网易163 </a>
需求:在每个链接后面加编号,结果
<a href="http://www.sina.com.cn/">新浪 </a>01 <a href="http://www.sohu.com/">搜狐 </a>02 <a href="http://www.qq.com/">腾讯QQ </a>03 <a href="http://www.163.com/">网易163 </a>04
代码实现:
string test = "<a href=/"http://www.sina.com.cn//">新浪</a><a href=/"http://www.sohu.com//">搜狐</a><a href=/"http://www.qq.com//">腾讯QQ</a><a href=/"http://www.163.com//">网易163</a>";
Regex reg = new Regex(@"(?is)<a[^>]*>(?:(?!</?a/b).)*</a>");
int i = 1;
string result = reg.Replace(test, delegate(Match m) { return m.Value + (i++).ToString("00"); });
richTextBox2.Text = result;
/*--------输出--------
<a href="http://www.sina.com.cn/">新浪</a>01<a href="http://www.sohu.com/">搜狐</a>02<a href="http://www.qq.com/">腾讯QQ</a>03<a href="http://www.163.com/">网易163</a>04
*/
这个需求是在链接后加编号,只要匹配到<a…>…</a>标签,在后面加上编号即可,但是由于编号是要根据a标签的个数来计数的,所以是动态变化的,这样直接替换就做不到了。而正则中的委托,是每次匹配成功后都会调用委托方法,而匹配是从左向右按顺序匹配的,所以调用委托方法也是按匹配的先后顺序进行调用的,这样就可以先用正则匹配出a标签,然后在委托方法中动态进行计数了。
3.2 逻辑判断
如果待替换的子串,需要根据当前匹配子串的内容,经过判断后决定如何替换,一般无法直接通过replace()实现,需求在委托方法里进行判断。
举例1:
源字符串:源字符串规律为“字母=数字”,用“&”相连
a=12&b=34&c=56&d=78
a=98&b=76&d=54
需求:如果源字符串有“c=数字”,就替换为“c=12”,否则在字符串结尾添加“&c=98”。
代码实现:
string[] test = new string[]{"a=12&b=34&c=56&d=78", "a=98&b=76&d=54"};
Regex reg = new Regex(@"(?is)(?<=^(?:(?!c=).)*)(?(c=[^&]+)c=[^&]+|$)");
foreach(string s in test)
{
richTextBox2.Text += "字符串: " + s + "/n";
richTextBox2.Text += "替换后: " + reg.Replace(s, delegate(Match m) { return m.Value == "" ? "&c=98" : "c=12"; }) + "/n/n";
}
/*--------输出--------
字符串: a=12&b=34&c=56&d=78
替换后: a=12&b=34&c=12&d=78
字符串: a=98&b=76&d=54
替换后: a=98&b=76&d=54&c=98
*/
还有一个类似的需求实例。
举例2(一个可能很简单的正式表达式求助):
源字符串:要处理的字符有可能是
""(空)
"p=1"
"ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907a"
"ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907a&p=2"
"ID=e2798a59&xx=79d5&p=4&bb=4833-9c57&cc=87d46a8&bb=b907a"
需求:对上述任何一种字符串的可能,查找是否有p=x,如果找不到,为字符串加上"p=0" ,如果找到,还要得到x的值,让y=x+1之后,再把"p=y"替换之前的p=x。
代码实现:
string[] test = new string[] { "", "p=1", "ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907a", "ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907a&p=2", "ID=e2798a59&xx=79d5&p=4&bb=4833-9c57&cc=87d46a8&bb=b907a" };
foreach (string s in test)
{
richTextBox2.Text += "原始字符串: /t" + s + "/n";
richTextBox2.Text += "替换后字符串: /t" + Regex.Replace(s, @"(?is)p=(?<v>/d+)|(?<!p=/d+.*)$", delegate(Match m) { if (m.Groups["v"].Value != "") return "p=" + (Convert.ToInt32(m.Groups["v"].Value) + 1); return "p=0"; }) + "/n/n";
}
/*--------输出--------
原始字符串:
替换后字符串: p=0
原始字符串: p=1
替换后字符串: p=2
原始字符串: ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907a
替换后字符串: ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907ap=0
原始字符串: ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907a&p=2
替换后字符串: ID=e2798a59&xx=79d5&bb=4833-9c57&cc=87d46a8&bb=b907a&p=3
原始字符串: ID=e2798a59&xx=79d5&p=4&bb=4833-9c57&cc=87d46a8&bb=b907a
替换后字符串: ID=e2798a59&xx=79d5&p=5&bb=4833-9c57&cc=87d46a8&bb=b907a
*/
这个需求中,既涉及到了对替换子串的逻辑判断,又涉及到了数字运算,直接替换做不到,所以要考虑使用委托。先通过正则匹本出p=x,再在委托方法中进行逻辑判断和运算。
3.3 多条件组合替换
当需求中的条件多于一个时,可能无法在一个正则表达式中进行判断,或者即使能够在一个正则表达式中判断,由于正则表达式非常复杂,会降低匹配效率,所以还是要在委托方法中进行替换。
举例1:
源字符串:第一个测试...<a href=/"www.test.com/">又一个测试</a>...第三个测试...<a href=/"www.test.com/" title=/"测试/" >第几个测试了?</a>...这是最后一个测试了...
需求:为字符串中的“测试”加链接,已有链接的不加。
这个需求,首先是要进行替换,但又加了一个附加条件,已有链接的不替换,这样如果在一个正则表达式中实现,正则太复杂,不但降低匹配效率,扩展起来也很困难,可读性也差,所以还是用正则委托来实现比较好。
先分析一下需求,在<a…>…</a>标签内的关键字不进行替换,那换个角度,只要先找出a标签外的字符串,对关键字进行替换就可以满足需求了。所以就是写正则,匹配出a标签外的子串,在委托方法中对关键字加链接,再替换回原字符串就可以了。
代码实现:
string test = "第一个测试...<a href=/"www.test.com/">又一个测试</a>...第三个测试...<a href=/"www.test.com/" title=/"测试/" >第几个测试了?</a>...这是最后一个测试了...";
Regex reg = new Regex(@"(?is)^((?!</?a).)+|</a>((?!</?a).)+");
string result = reg.Replace(test, delegate(Match m) { return m.Value.Replace("测试", "<a href=/"www.test.com/">测试</a>"); });
richTextBox2.Text = result;
/*--------输出--------
第一个<a href="www.test.com">测试</a>...<a href="www.test.com">又一个测试</a>...第三个<a href="www.test.com">测试</a>...<a href="www.test.com" title="测试" >第几个测试了?</a>...这是最后一个<a href="www.test.com">测试</a>了...
*/
当然,这个例子并不严谨,因为其它标签中也可能出现关键字,而这些关键通常也是不应该被替换的,这时也可以在委托方法中进行判断,以确定是否应该被替换。
举例2(正则去除不包含特定字符串的A标签~):
源字符串:<a href=www.abc.com>abc </a>啊啊啊 <a href=bcd.com>abc </a>啊啊啊 <a href="www.abc.com" class="t1">abc </a>啊啊啊 <a href=def.com>abc </a>啊啊啊 <a href=efg.com>abc </a>
需求:把链接中不包含“abc”的超链接过滤掉。
这个需求,实际上也是两个条件,首先是要做替换,然后附加了一个条件,链接中不包含“abc”的替换。类似于这种符合某一规律的子串,部分替换,部分保留的情况,通常比较适合用正则委托来解决。
当然,这个需求还是可以直接通过一个正则表达式来处理的,先看一下这种处理方式的代码。
string test = "<a href=www.abc.com>abc </a>啊啊啊 <a href=bcd.com>abc </a>啊啊啊 <a href=/"www.abc.com/" class=/"t1/">abc </a>啊啊啊 <a href=def.com>abc </a>啊啊啊 <a href=efg.com>abc </a> ";
Regex reg = new Regex(@"(?is)<a(?:(?!href=).)*href=(['""]?)(?:(?!abc|['""/s>]).)+/1(?:/s[^>]*)?>((?:(?!</?a/b).)*)</a>");
string result = reg.Replace(test, "$2");
richTextBox2.Text = result;
/*--------输出--------
<a href=www.abc.com>abc </a>啊啊啊 abc 啊啊啊 <a href="www.abc.com" class="t1">abc </a>啊啊啊 abc 啊啊啊 abc
*/
可以看到,这种处理方式,是先进行判断,再进行匹配。在正则表达式中,对链接子串的每一个字符用“(?!abc|['""/s>]).”进行判断,所以有多少个字符,就要判断多少次,在这种情况下,通常需要使用“|”来对不同的条件取“或”,而“|”的效率一般是比较低的。
另一种处理方式,是先把链接匹配出来,然后在委托方法中进行判断,以决定是否替换。
代码实现:
string test = "<a href=www.abc.com>abc </a>啊啊啊 <a href=bcd.com>abc </a>啊啊啊 <a href=/"www.abc.com/" class=/"t1/">abc </a>啊啊啊 <a href=def.com>abc </a>啊啊啊 <a href=efg.com>abc </a> ";
Regex reg = new Regex(@"(?is)<a(?:(?!href=).)*href=(['""]?)([^'""/s>]+)/1[^>]*>((?:(?!</?a/b).)*)</a>");
string result = reg.Replace(test, delegate(Match m) { if (m.Groups[2].Value.IndexOf("abc") > -1) return m.Value; return m.Groups[3].Value; });
richTextBox2.Text = result;
/*--------输出--------
<a href=www.abc.com>abc </a>啊啊啊 abc 啊啊啊 <a href="www.abc.com" class="t1">abc </a>啊啊啊 abc 啊啊啊 abc
*/
这种处理方式,是先进行匹配,再进行判断。先通过正则把每一个链接都匹配出来,作为参数传给委托方法,在委托方法中判断是否包含“abc”,以决定是否替换。这种方式因为匹配过程中不需要进行判断,所以匹配的速度是很快的,然后在委托方法中只执行一次判断即可。两种处理方式的效率,在字符较少时区别不大,在字符较多,调用较频繁的情况下,还是委托方法的效率比较高。
类似于这种需求,在效率、可读性、可扩展性等方面综合考虑,还是使用委托方法要好一些。
转自:http://blog.csdn.net/lxcnn/article/details/4711491
发表评论
-
(从网上考过来的,收藏) javascript 正则表达式的贪婪与非贪婪
2012-10-08 10:35 891以下内容转自:http://www.cnitblog.com ... -
正则表达式常用验证
2011-08-24 12:20 856在前台很多地方需要验证输入格式,为了方便以后使用,把常用的整理 ... -
正则判断一个字符串里是否包含一些词
2011-08-16 16:53 3270今天项目里用到了正则,判断一个字符串里是不是包含这些词,词出 ... -
js取当前url参数
2011-07-19 11:14 1952js没有提供取当前url参数的方法,只能是自己从中截取了,在 ... -
正则手册
2011-07-07 16:53 1030给大家共享个正则手册 欢迎查看本人博客: ... -
[ ] 字符组(Character Classes) .
2011-07-06 17:31 829[]能够匹配所包含的一系列字符中的任意一个。需要注意的是,[ ... -
正则基础之——捕获组(capture group) .
2011-07-06 17:30 10061 概述 1.1 什么是捕获组 ... -
正则表达式学习参考
2011-07-06 17:28 777正则表达式学习参考 1 ... -
正则基础之——小数点 .
2011-07-06 17:23 794小数点可以匹配除了换行符“/n”以外的任意一个字符 一 ... -
正则基础之——NFA引擎匹配原理 .
2011-07-06 17:22 1002NFA引擎匹配原理 1 ... -
正则基础之——环视 .
2011-07-06 17:21 572环视只进行子表达式的匹配,不占有字符,匹配到的内容不保存到最终 ... -
正则基础之——/b 单词边界 .
2011-07-06 17:20 8261 概述 “/b”匹配单词边界,不匹配任何 ... -
正则应用之——日期正则表达式
2011-07-06 17:18 10751 概述 首先需要说明的一点,无论是Win ... -
.NET正则基础之——.NET正则匹配模式 .
2011-07-06 17:16 23371 概述 匹配模式指的是一些可以改变正则表 ... -
.NET正则基础之——平衡组 .
2011-07-06 17:14 18181 概述 平衡组是微软在.NET中提出的一 ... -
正则基础之——非捕获组 .
2011-07-06 17:10 1370非捕获组:(?:Expression) 接触正则表达式不久的 ... -
正则基础之——反向引用 .
2011-07-06 17:09 13261 概述 捕获组捕获到的内容,不仅可以在 ... -
.NET正则基础——.NET正则类及方法应用 .
2011-07-06 17:07 11081 概述 初学 ... -
正则基础之——贪婪与非贪婪模式 .
2011-07-06 17:03 9661 概述 贪婪 ... -
正则应用之——逆序环视探索
2011-07-06 17:01 12151 问题引出 前几天在CSDN论坛遇到这样 ...
相关推荐
在编程领域,C#语言提供了一种强大的工具——正则表达式,用于处理字符串和验证数据格式。正则表达式是一种模式匹配语言,它能够帮助我们有效地检查、查找、替换和提取文本。在C#中,我们可以使用System.Text....
1.4.35 Regex类——正则表达式 76 1.4.36 Split方法——分割字符串 78 1.4.37 String类——字符串 79 1.4.38 StringBuilder类——可变字符串 82 1.4.39 Substring方法——截取字符串 83 1.4.40 TimeSpan对象——表示...
至于"regex"标签,它强调了RegexCompare 4.0的核心功能——正则表达式操作。软件提供了丰富的正则表达式功能,包括常见的元字符、量词、分组、选择、锚点等,以及高级特性的支持,如后向引用、捕获组、非捕获组等。...
- **字符串与正则表达式**:字符串方法(substring、indexOf、replace等)和正则表达式的使用。 3. **DOM操作**: - **选择元素**:getElementById、getElementsByClassName、getElementsByTagName、...
VB提供了多种方法实现数据验证,如正则表达式验证、自定义函数验证等。 6. **异常处理**:在程序运行过程中可能会出现错误,如数据库连接失败、数据操作异常等。VB提供了Try...Catch...Finally结构来捕获和处理这些...
第21天 01为什么会有委托 02泛型委托 03多播委托 04使用委托进行窗体传值 05事件 06事件 07程序集的引用 07Common 08反射的常用函数 09用反射制作计算器 第22天 01 SqlConnection 数据库 02...
4. **C#的进阶编程**:涵盖异常处理、枚举类型和结构类型、委托和事件、字符串和正则表达式以及集合和泛型的使用,这些都是提升编程效率和代码复用的重要工具。 5. **创建Windows应用程序**:涉及常用窗体控件、...
本合集包含了两份重要的JavaScript参考手册——“JavaScript语言中文参考手册”和“JavaScript参考手册”,它们是深入理解和掌握JavaScript的重要资源。 **JavaScript语言中文参考手册** 这份手册详细阐述了...
5. **函数与委托**:第6章可能讲解了函数的定义、参数传递以及委托和事件的概念,这些都是C#中实现模块化和事件驱动编程的关键。 6. **面向对象高级特性**:第8、9、10章可能深入讨论了接口、抽象类、泛型、匿名...
教程1——"Visual C# 2010 从入门到精通视频教程",主要介绍了C#的基础知识,包括变量、运算符、表达式、控制流(如判断语句和循环语句)、异常处理、面向对象编程(类与对象、值类型和引用类型)、枚举和结构体、...
实例4 TextBar控件应用举例——交通肇事申辩系统 实例5 使用正则表达式实现数据验证1 实例6 使用正则表达式实现数据验证2 实例7 Asp.net(C#)实现验证码功能 实例8 使用DataList建立一个留言板 ...
6. **正则表达式**:详细解释正则表达式的语法和用法,用于文本处理和模式匹配。 7. **错误处理**:如何使用try...catch进行错误捕获和处理。 8. **DOM操作**:讲解如何通过JavaScript操作文档对象模型(DOM),...
本文将深入探讨jQuery 2.1.1版本的两个核心文件——`jquery-2.1.1.js`(未压缩版)和`jquery.min-2.1.1.js`(压缩版),帮助读者理解其内部机制和优化策略。 1. **jQuery的核心功能** - DOM操作:jQuery提供了一套...
1. **基础语法**:介绍JavaScript的基础结构,包括变量声明(var、let、const)、数据类型(如字符串、数字、布尔值、null、undefined、对象、数组、Symbol等)、操作符(算术、比较、逻辑、赋值、三元运算符等)...
1. **基础语法**:JavaScript的基础包括变量、数据类型(如字符串、数字、布尔值、null、undefined)、操作符(算术、比较、逻辑等)、流程控制(条件语句if...else、switch,循环语句for、while、do...while)以及...
9. **正则表达式**:匹配模式,分组,替换,边界,标志等正则表达式的使用。 10. **ES6新特性**:let和const、模板字符串、解构赋值、箭头函数、类和模块系统。 11. **DOM遍历和选择**:了解和使用DOM遍历方法(如...