对以下正则单步分解小块详细解说一下,如何写这样的正则
//委托方法
private string RegReplace(Match m)
{
Regex regValue = new Regex(@"(?<=showCabinInfo\(\s*)('[^']*',?)+(?=\))");
return regValue.Match(m.Groups["values"].Value).Value + "," + m.Groups["content"].Value + "~";
}Regex regSpan = new Regex(@"(?is)(?<=<td[^>]*>[^<]*(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*)\s*<span(?<values>[^>]*)>\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*</span>\s*(?=(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*</td>)"); string result = regSpan.Replace(test, new MatchEvaluator(RegReplace));
richTextBox2.Text = result;
//委托方法
private string RegReplace(Match m)
{
Regex regValue = new Regex(@"(?<=showCabinInfo\(\s*)('[^']*',?)+(?=\))");
return regValue.Match(m.Groups["values"].Value).Value + "," + m.Groups["content"].Value + "~";
}Regex regSpan = new Regex(@"(?is)(?<=<td[^>]*>[^<]*(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*)\s*<span(?<values>[^>]*)>\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*</span>\s*(?=(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*</td>)"); string result = regSpan.Replace(test, new MatchEvaluator(RegReplace));
richTextBox2.Text = result;
解决方案 »
- ASP.NET在IE9中的document.getElementById如何用。
- 存储过程中临时表DROP的位置放哪里啊
- Gridview手写代码分页有错 在线等!!!
- 请求一URL重写 (Demo/Code)
- If也出错?________!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()_+!@#$%^&*()
- 为了谢谢大家的回答,另开贴问上个问题的问题!
- ASP.NET GridView获取值
- asp.net根据IP来源判断?????
- 关于。net环境的配置。请教
- 请问在哪下载treeview控件?
- 想用gridview实现以下效果,请问各位高手有什么好方法
- 问一个sliverlight传参的问题?
1、存在于<td...>和</td>之间
2、可以提取出公共规律的部分为<span...>...</span>
3、符合条件2的子串可能有一个或多个
这样的复杂度就不适合用一个正则直接替换了,所以想到用正则委托,但事实上这并不是正则委托典型的应用场景。使用委托可以把符合一定规律的子串先提取出来,做一定的处理后,再替换回子串所在的位置。因为是在委托方法内处理,所以可以做很多如运算等复杂的处理,而不仅仅是字符串的操作。这样分析之后,就要把符合规律的子串提取出来,以Match对象为参数传给委托方法处理。那就分析一下要提取子串的规律,来写下正则
1、是一个<span...>...</span>子串,<span...>中包含onmouseover属性,且符合onmouseover="...('...','...'...)"这样的规律
2、前面为<td...>和任意多个<span...>...</span>子串
3、后面为任意多个<span...>...</span>子串和</td>分别写出对应的正则
//1、是一个<span...>...</span>子串,<span...>中包含onmouseover属性,且符合onmouseover="...('...','...'...)"这样的规律
\s*<span(?<values>[^>]*)>\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*</span>\s*
//2、前面为<td...>和任意多个<span...>...</span>子串
(?<=<td[^>]*>[^<]*(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*)
//3、后面为任意多个<span...>...</span>子串和</td>
(?=(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*</td>)提取出相应的子串后,就是在委托方法中进行一下处理,取出onmouseover属性的内容和<span...>和</span>之间的内容,并补充一些“,”、“~”之类的内容,再替换回子串所在的位置就可以了。
当然,我上面可能考虑得过于复杂了,如果是所有带有onmouseover属性的<span...>都符合这一规律,完全可以一个正则搞定,可以试下这样是否符合要求
Regex regSpan = new Regex(@"(?is)\s*<span(?:(?!onmouseover=).)*onmouseover=""[^,(]*\(\s*(?<value>[^"")>]*)\)""[^>]*>\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*</span>\s*");
string result = regSpan.Replace(yourStr, "${value},${content}~");
richTextBox2.Text = result;这里只是根据<span和onmouseover来进行替换,而没有考虑是否在<td...>和</td>之间。
1我用的工具是MTracer2.0 但我发现如果将正则放到哪里面,好像不能得到正确结果,需要用什么工具来测试呢,
2我对正则中的前后连接效果十分不解,
比如c#的语法;号就是一个句子终结,一般情况大多语句的执行规则是由左向右,但像这样复杂的正则,里面的 * . 这些匹配符它可以前后都使用,我无法把握如何对正则分割哪里,正则有块结束符吗或有什么规定来完成这种分割。》\s*<span(?<values>[^>]*)>\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*</span>\s*
如上语句我看就就会出现这样困扰
1、\s*<span(?<values>[^>]*)>\s*
2、(?<content>(?:(?!</?span\b).)*)
3、(?<!\s)\s*</span>\s*
或这样
1、\s*<span(?<values>[^>]*)>
2、\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*
3、</span>\s*
RegexBuddy第一次用给我的结果就是错的,后来就懒得用了
2、正则中没有类似的概念
“?”、“*”、“+”、“{m,n}”等是量词
如果前面没有用“()”限定范围,那它修饰的就是一个字符或是一个元字符。比如“a+”,表示一个以上的字符“a”,也就是可以匹配“a”,“aaa”,“aaaaaaaaa”等等;或者如“\s*”表示0个或任意多个空白字符
如果前面用了“()”来限定范围,那么它修饰的就是“()”内的整体。比如“(abc)+”,表示一个以上的字符串“abc”,也就是可以匹配“abc”,“abcabc”,“abcabcabcabc”等等。\s* 表示任意多个空白字符
(?<values>[^>]*) 是命名捕获组,语法(?<name>Expression)
(?:Expression) 非捕获组
(?!Exp)、(?=Exp)、(?<!Exp)、(?<=Exp) 都是环视以上这些语法规则在我的博客里都有介绍的
我想问一下,你写这个正则是用1 2 3 来增加的的顺序吗,能否对1 2 3 步再进行解分 分解到10步左右,让我理解一下如何变化的。
引用前面代码
//1、是一个<span...>...</span>子串,<span...>中包含onmouseover属性,且符合onmouseover="...('...','...'...)"这样的规律
\s*<span(?<values>[^>]*)>\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*</span>\s*
//2、前面为<td...>和任意多个<span...>...</span>子串
(?<=<td[^>]*>[^<]*(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*)
//3、后面为任意多个<span...>...</span>子串和</td>
(?=(<span[^>]*>(?:(?!</?span\b).)*</span>\s*)*</td>)
首先是对需求的明确和分析,只有需求明确,才能确定究竟使用哪种方法处理、怎样处理才能达到最优
需求分析,确定使用的方法后,才会进行具体的实现,也就是正则的书写
具体实现时要找出字符串的规律,是否能过一个正则表达式实现,一个表达式是否合理,有时为了提高可读性、可扩展性和效率,可能需要把正则分成多个来写,注意,并不是一个正则实现的效率就一定比多个正则实现的效率高,要看场景和正则的复杂度就楼主的需求,首先确认是一个替换的需求,使用Replace方法,由于需要对替换的内容进行一些处理,所以需要用到委托方法
字符串分析过程基本上就是由整到零,正则的书写过程基本上就是由零到整,我虽然不会去套用这样一种模式,而主要是在脑中分析和考虑,但也基本上可以认为是这样一个分析过程
需要替换的是什么样的字符串,基本上就可以按这三条来总结规律:
1、是一个 <span...>... </span>子串, <span...>中包含onmouseover属性,且符合onmouseover="...('...','...'...)"这样的规律
2、前面为 <td...>和任意多个 <span...>... </span>子串
3、后面为任意多个 <span...>... </span>子串和 </td>
各条之间基本上没有什么影响,就可以单独实现后组合一下
其实这些分步正则也没什么好解释的,写的多了,自然就知道该采用什么样的语法了,说下第一条的分析和书写过程吧
<span开头,前面可能有多个空白字符,就是
\s*<span
然后是任意多个不是“>”的字符,一直匹配到“>”为止,也就是<span...>标签,由于其中的内容需要在委托方法中做二次处理,所以用个捕获组来捕获
(?<values>[^>]*)>
然后就是<span...>和</span>之间的内容
(?:(?!</?span\b).)* 因为<span...>和</span>之间不可以再出现“<span”和“</span”,所以这就表示任意一个从它开始,右侧不能是<span或</span的字符,这样的字符可以有任意多个
用一个捕获组来捕获,就是
(?<content>(?:(?!</?span\b).)*)
因为它两侧可能出现空白字符,而这些空白字符在替换结果中是不需要的,所以不应包含在捕获组中,前面的\s*匹配的开头的空白字符,后面的(?<!\s)表示捕获组捕获内容最后不能是空白字符,也就是匹配到空白字符为止,而结尾的空白字符则由后面的\s*来匹配,也就是
\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*
接下来就是</span>和,后面还可能有空白字符,也就是
</span>\s*
合起来就是
\s*<span(?<values>[^>]*)>\s*(?<content>(?:(?!</?span\b).)*)(?<!\s)\s*</span>\s* 其它两条和这个差不多,只是用到了环视的语法,这些语法在我的博客中都有讲解正则因为比较抽象,刚开始学的时候会有些不知道从哪里入手,多看一些,多动手练习一下,其实还是很容易掌握的
楼主的这个需求我可以讲解的很详细,但是如果想真正理解,还是对基本的语法规则有所了解的,如果想真正掌握,还需要自己多动手去写
我开始学正则时,基本上就是在论坛里先翻老帖子,看别人怎么写,然后有了新帖子,就试着自己动手去写,写得出就回一下帖,写不出就看别人是怎么写的,久而久之也就会了