posts - 1,  comments - 15,  trackbacks - 0
三、正则中几个难点

1、贪婪与非贪婪
 
有助于理解这一概念的帖子      http://community.csdn.net/Expert/topic/5435/5435240.xml?temp=.7199671
 
注意      在谈到贪婪与非贪婪时,有一点大家可能会忽略,那就是单独的一个“?”,表示的是贪婪模式,而“??”才是非贪婪模式。
        举例:
       源字符串:12
       正则表达式(一):[1-9]\d?
       正则表达式(二):[1-9]\d??
       结果:(一)匹配成功,匹配结果为12,(二)匹配成功,匹配结果为1
 
2、正向预搜索和反向预搜索

有助于理解这一概念的帖子      http://community.csdn.net/Expert/topic/5410/5410564.xml?temp=.1138422
 

四、正则的几种常见用法


1、验证控件 RegularExpressionValidator

注意      1、RegularExpressionValidator不能验证非空,验证非空用RequiredFieldValidator,名司其职
      2、如无特殊情况,用于验证控件的正则前后分别要加“^”和“$”,因为用验证控件来验证的内容是要完全匹配的,而不是成功匹配其中一部分即可通过验证
      3、用于验证控件的正则,最后都要转换为客户端脚本,而由于脚本语言对正则的支持较弱,有些在cs程序里可以通过的正则,在验证控件里可能失效
 
有助于理解这一概念的帖子      http://community.csdn.net/Expert/topic/5445/5445334.xml?temp=.3749658
 

2、匹配

        匹配就是检查字符串是否满足某一规律,或是否包含符合某一规律的子字符串
  
        Regex.IsMatch
 
举例      判断textBox1输入内容是否为yyyy-MM格式
string yourStr = textBox1.Text;
if(Regex.IsMatch(yourStr, @"^\d{4}-(0\d|1[0-2])$"))
 
{
                MessageBox.Show(
"符合");
}

          
else
{
               MessageBox.Show(
"不符合");
}


3、提取

       提取就是从字符串中取出符合某一规律的子字符串
       Match m = Regex.Match
       MatchCollection mc = Regex.Matches
       前者用来取出单一匹配结果,后者用来取出多个匹配结果,并存入集合

举例取出单个图片地址
string yourStr = "<img src=\"http://www.ahelp.cn/bbs/UploadFile/2006-8/200681516161698723.jpg\" border=\"0\" alt=\"\"/>";            
string resultStr = "";
Match m 
= Regex.Match(yourStr, @"<img\s[^>]*?src=([""']?)(?<source>[^""'\s]*)\1[^>]*?>", RegexOptions.IgnoreCase);
if (m.Success)
{
    resultStr 
= m.Groups["source"].Value;
}
取出多个图片地址
string yourStr = "<p><img src=\"http://www.ahelp.cn/bbs/UploadFile/2006-8/200681516161698723.jpg\" border=\"0\" alt=\"\"/></p><p>&nbsp;</p><p><img src=\"http://www.ahelp.cn/bbs/UploadFile/2006-8/200681516194447448.jpg\" border=\"0\" alt=\"\"/></p><p>&nbsp;</p><img src=\"http://photo.bababian.com/20060803/C97D6403CD4F2F85A5FBB57D5A791F5B_500.jpg\" border=\"0\" alt=\"\"/>";
MatchCollection mc = Regex.Matches(yourStr, @"<img\s[^>]*?src=([""']?)(?<src>[^""'\s]*)\1[^>]*?>", RegexOptions.IgnoreCase);
foreach (Match m in mc)
{
    richTextBox2.Text 
+= m.Groups["src"].Value + "\n";
}

有助于理解这一概念的帖子      http://community.csdn.net/Expert/topic/5479/5479400.xml?temp=.2616083
      http://community.csdn.net/Expert/topic/5441/5441044.xml?temp=.3489954


4、替换

       替换就是将一种形式的字符串替换为另一种形式,或是删除不需要的内容

       Regex.Replace

举例将UBB代码转换为html格式
string test = "[img]http://www.csdn.net/logo.jpg[/img]";
string resultStr = Regex.Replace(test, @"\[img\]([^\]]*?)\[/img\]"@"<img src=""$1"">");
输出为:<img src="http://www.csdn.net/logo.jpg">

举例 取出<td>...</td>标签内非html代码部分
string test = "<TD CLASS=btd WIDTH=198 BGCOLOR=\"#FCFCFC\"><B>  <a href=\"http://dict.pconline.com.cn/dic/sort.jsp?kindId=-1&dicId=3142\" target=\"_blank\">显示屏类型</a></B></TD>";
string resultStr = Regex.Replace(test, @"<[^>]*?>","").Trim();
输出为:显示屏类型


5、分割

       Regex.Split

注意      在Split中使用捕获组,分割后的数组也包含捕获组的内容,即使使用零宽度捕获组,仍然会将捕获组的内容保存到结果数组内

举例不存在捕获组时   
string test = "aa<bbb>cc<ddd>ee";
string[] temp = Regex.Split(test, @"<[^>]*?>");
foreach (string s in temp)
{
     richTextBox2.Text 
+= s + "\n";
}
输出为:
aa
cc
ee

存在捕获组时
string test = "aa<bbb>cc<ddd>ee";
string[] temp = Regex.Split(test, @"(<[^>]*?>)");
foreach (string s in temp)
{
    richTextBox2.Text 
+= s + "\n";
}
输出为:
aa
<bbb>
cc
<ddd>
ee


有助于理解这一概念的帖子      http://community.csdn.net/Expert/topic/5436/5436187.xml?temp=.7995264


6、委托
      
      正则中的委托,有时候可以很优雅的解决某一类问题,或是提高效率
      委托一般用在对符合某一条件的子字符串进行处理,而不是处理所有

      MatchEvaluator(string (Match) target)

举例      只替换<B>...</B>标签内不包含html代码的部分为CRT
private void button2_Click(object sender, EventArgs e)
{
      string yourStr = "<TD CLASS=btd WIDTH=198 BGCOLOR=\"#FCFCFC\"><B>  <a href=\"http://dict.pconline.com.cn/dic/sort.jsp?kindId=-1&dicId=3142\" target=\"_blank\">显示屏类型</a></B> <B>   WUXGA+</B></TD>";
      string resultStr = Regex.Replace(yourStr, @"(?<=<b[^>]*>)[^<>]*(?=</b>)", new MatchEvaluator(expReplace), RegexOptions.IgnoreCase);

}


private string expReplace(Match m)
{
    
return m.Value.Replace(m.Value, "CRT");
}
输出为:<TD CLASS=btd WIDTH=198 BGCOLOR="#FCFCFC"><B>  <a href="http://dict.pconline.com.cn/dic/sort.jsp?kindId=-1&dicId=3142" target="_blank">显示屏类型</a></B> <B>CRT</B></TD>

有助于理解这一概念的帖子      http://community.csdn.net/Expert/topic/5520/5520530.xml?temp=.769314
      http://community.csdn.net/Expert/topic/5580/5580796.xml?temp=.6849176
      http://community.csdn.net/Expert/topic/5578/5578425.xml?temp=.2284815



 
posted @ 2007-05-16 09:20 -过客- 阅读(346) 评论(1) 编辑
五、一些常用正则

      事实上,我并不提倡列举一些常用正则,因为正则通常情况下都是具体问题具体分析,而不是生搬硬套的,不过有些正则大家知道一下还是有好外的,也可以在自己写正则的时候做下参考

视情况陆续更新
 
1、匹配任意中文字符  
[\u4e00-\u9fa5]
 
2、匹配手机的正则 
^1(3\d|5[389])\d{8}$
 
3、匹配座机的正则
格式:010-12345678 区号可有可无,座机号为7或8位
^(0(10|2[0-57-9]|[3-9]\d{2})-)?\d{7,8}$

4、日期正则
 
格式为yyyy-MM-dd,或yyyy-M-d,其中的连接符可以为“-”、“/”、“.”,年份为1600-9999,带闰年判断

^(?:(?:(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|
[3579][26])00)))([-/.])(?:0?2\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\d)?\d{2})([-/.])(?:(?:(?:0?
[13578]|1[02])\2(?:31))|(?:(?:0?[13-9]|1[0-2])\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\2(?:0?
[1-9]|1\d|2[0-8]))))$

5、IP地址

^(?:(?:[1-9]?[0-9]|1[0-9]{2}|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:[1-9]?[0-9]|1[0-9]{2}|2(?:[0-4][0-9]|5[0-5]))$
posted @ 2007-05-16 09:20 -过客- 阅读(476) 评论(0) 编辑
      本文只是我正则学习过程中积累的一点经验,为初学者提供参考

      如无特殊说明,本文仅就C#中的正则应用进行讨论,由于本人水平有限,整理时间仓促, 有错误的地方还请大家批评指正,我会及时更正并陆续增加一些新的内容
一、推荐一篇文章+一个工具+一个正则学习方法

       教程: http://www.regexlab.com/zh/regref.htm

       工具:match tracer 1.2

      本人水平有限,教程是写不了的,所以推荐上面的一篇正则教程,这是我认为,至少在入门级中文教程里,最好的教程。

      学习正则最好的方法就是做大量的练习,在CSDN上以“正则”为关键字搜索帖子,先不要看回复,看楼主的要求,自己参考教程试着写,得到正确结果,或是自己实在做不出时,再去看回复,这样大概有个百十来个帖子,你的正则基本应用就该没问题了。
 
二、初学正则的几个误区

1、. 小数点可以匹配除了换行符(\n)以外的任意一个字符
       如要匹配小数点本身,需要加个“\”进行转义
       在匹配多行时,不要试图用[.\n]来匹配任意字符,可以使用(.|\n),但一般不这样用,一般用[\s\S],或者是用.加RegexOptions.Singleline参数来达到这一效果
 
2、[] 使用方括号 [ ] 包含一系列字符,能够匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能够匹配其中字符之外的任意一个字符。同样的道理,虽然可以匹配其中任意一个,但是只能是一个,不是多个。
 
       记住[]匹配的只能是一个字符,不是多个。新手最容易犯的错误就是,用[^abc]这样的表达式来匹配不包含“abc”子字符串的字符串
     
举例
       源字符串:string yourStr = "<aaa>bbb<abc>ccc<ddd>";
       结果:<aaa>、<ddd>
       即取出yourStr中为<...>,但<>中不是abc的内容
       错误写法:<[^abc]*>
       正确写法:<(?!abc>)[^>]*>
       
       另外就是,大部分在正则中有特殊意义、在匹配其本身时需转义的字符,在[]内是不需要转义的。必须转义的只有“\”、“[”和“]”,而“^”出现在[]开始位置,“-”前后构成范围区间时,需要转义,出现在其它位置不需要转义,如
       [\^ .$^{\[(|)*+?\\-]

    
3、\w 任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个
       一般来说,是这样的,但是在某些情况下,\w也会匹配本地字符集,比如中文系统的中文,所以在明确要求是A~Z,a~z,0~9,_ 中的一个的时候,用[A-Za-z0-9_],而不用\w
 
4、\转义    一些在正则中具有特殊意义的字符,如想匹配这些字符本身,需要用“\”对其进行转义。
       参考
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_fxfund/html/f49cc9cc-db7d-4058-8b8a-422bc08b29b0.htm

       在实际应用中,根据具体情况,需要转义的字符可能不止如下所列字符
        .$ ^ { [ ( | ) * + ? \
 
       另外,\s,\b,\w,\d等等这些在正则中有特殊意义的字符,用在字符串""中时,需要进行两次转义,即
       string pattern = "the \\b\\w+\\b number is \\d";
       或者是在前面加一个“@”,取消转义
       string pattern = @"the \b\w+\b number is \d";

       比较特殊的是“"”,用在不带@的字符串中时,用\"来进行转义,用在带@的字符串中时,用""来进行转义
       string pattern = "<img\s+src=\"[^\"]*\"\s*>";
       string pattern = @"<img\s+src=""[^""]*""\s*>";


5、|    “|”是以()划分范围的,如果在“|”的左右两侧没有()来限定范围,那么它的作用范围即为“|”左右两侧整体,如
 
举例     
      (1)、  ^\d+\.\d|\d+$
      (2)、  ^(\d+\.\d)|(\d+)$
      (3)、  ^(\d+\.\d|\d+)$
       (1)和(2)的效果是一样的,表示“|”两侧整体为“或”的关系,即^\d+\.\d或\d+$
       而(3)的结果与上面两个是不同的,因为它表示\d+\.\d和\d+为“或”的关系,这个表达式相当于^\d+\.\d$|^\d+$
       
      如:123.45
      (1)和(2)匹配成功,匹配结果为123.4
      (3)匹配失败,因为这个式子要求,或者为不带小数点的数字,或者小数点后最多带一位小数
       
       多个“|”时,同样以()划分作用范围
 
       “|”的匹配顺序为从左到右,当左侧不满足要求时,再去尝试匹配右侧表达式,如果左侧匹配成功,将不再尝试匹配右侧表达式,多个“|”时,从左向右依次尝试匹配
 
       顺便说一下,[]本身就隐含了“或”的关系,在[]中使用“|”表示“或”的关系是不对的,这样做只是多了一个普通字符“|”,用来匹配“|”字符本身,()也是同样道理
 
有助于理解这一概念的帖子      http://community.csdn.net/Expert/topic/5474/5474473.xml?temp=.9890863
 
6、RegexOptions.Singleline | RegexOptions .Multiline
 
       一些新手仅从字面上理解,以为这两个属性是互斥的,而事实上并非如此,它们是用来改变特定符号在正则表达式中的含义的。

       RegexOptions.Singleline  指定单行模式。更改点 (.) 的含义,使它与每一个字符匹配(而不是与除 \n 之外的每个字符匹配)。
       RegexOptions .Multiline 多行模式。更改 ^ 和 $ 的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。

posted @ 2007-05-16 09:19 -过客- 阅读(836) 评论(7) 编辑