C#正则表达式整理备忘

C#正则表达式整理备忘
(1) “@” 符号  
“@”
虽然并非 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 外的任意字符  
[…]   
匹配 [] 内所列出的所有字符  
[^…] 
匹配非 [] 内所列出的字符  
下面提供一些简单的示例:
1.    string  i =  "/n" ;
2.    string  m =  "3" ;
3.    Regex r =  new  Regex(@ "/D" );
4.    // Regex r = new Regex("//D");
5.    //r.IsMatch(i) 结果: true
6.    //r.IsMatch(m) 结果: false
7.     
8.    string  i =  "%" ;
9.    string  m =  "3" ;
10. Regex r =  new  Regex( "[a-z0-9]" );
11. // 匹配小写字母或数字字符
12. //r.IsMatch(i) 结果: false
13. //r.IsMatch(m) 结果: true
(3) 定位字符
定位字符 所代表的是一个虚的字符,它代表一个位置,你也可以直观地认为 定位字符 所代表的是某个字符与字符间的那个微小间隙。
^       
表示其后的字符必须位于字符串的开始处
$       
表示其前面的字符必须位于字符串的结束处
/b      
匹配一个单词的边界
/B     
匹配一个非单词的边界
另外,还包括: /A  前面的字符必须位于字符处的开始处, /z  前面的字符必须位于字符串的结束处, /Z  前面的字符必须位于字符串的结束处,或者位于换行符前
下面提供一些简单的示例:
1.    string  i =  "Live for nothing,die for something" ;
2.    Regex r1 =  new  Regex( "^Live for nothing,die for something$" );
3.    //r1.IsMatch(i) true
4.    Regex r2 =  new  Regex( "^Live for nothing,die for some$" );
5.    //r2.IsMatch(i) false
6.    Regex r3 =  new  Regex( "^Live for nothing,die for some" );
7.    //r3.IsMatch(i) true
8.     
9.    string  i = @"Live  for  nothing,
10. die  for  something"; // 多行
11. Regex r1 =  new  Regex( "^Live for nothing,die for something$" );
12. Console.WriteLine( "r1 match count:"  + r1.Matches(i).Count); //0
13. Regex r2 =  new  Regex( "^Live for nothing,die for something$" , RegexOptions.Multiline);
14. Console.WriteLine( "r2 match count:"  + r2.Matches(i).Count); //0
15. Regex r3 =  new  Regex( "^Live for nothing,/r/ndie for something$" );
16. Console.WriteLine( "r3 match count:"  + r3.Matches(i).Count); //1
17. Regex r4 =  new  Regex( "^Live for nothing,$" );
18. Console.WriteLine( "r4 match count:"  + r4.Matches(i).Count); //0
19. Regex r5 =  new  Regex( "^Live for nothing,$" , RegexOptions.Multiline);
20. Console.WriteLine( "r5 match count:"  + r5.Matches(i).Count); //0
21. Regex r6 =  new  Regex( "^Live for nothing,/r/n$" );
22. Console.WriteLine( "r6 match count:"  + r6.Matches(i).Count); //0
23. Regex r7 =  new  Regex( "^Live for nothing,/r/n$" , RegexOptions.Multiline);
24. Console.WriteLine( "r7 match count:"  + r7.Matches(i).Count); //0
25. Regex r8 =  new  Regex( "^Live for nothing,/r$" );
26. Console.WriteLine( "r8 match count:"  + r8.Matches(i).Count); //0
27. Regex r9 =  new  Regex( "^Live for nothing,/r$" , RegexOptions.Multiline);
28. Console.WriteLine( "r9 match count:"  + r9.Matches(i).Count); //1
29. Regex r10 =  new  Regex( "^die for something$" );
30. Console.WriteLine( "r10 match count:"  + r10.Matches(i).Count); //0
31. Regex r11 =  new  Regex( "^die for something$" , RegexOptions.Multiline);
32. Console.WriteLine( "r11 match count:"  + r11.Matches(i).Count); //1
33. Regex r12 =  new  Regex( "^" );
34. Console.WriteLine( "r12 match count:"  + r12.Matches(i).Count); //1
35. Regex r13 =  new  Regex( "$" );
36. Console.WriteLine( "r13 match count:"  + r13.Matches(i).Count); //1
37. Regex r14 =  new  Regex( "^" , RegexOptions.Multiline);
38. Console.WriteLine( "r14 match count:"  + r14.Matches(i).Count); //2
39. Regex r15 =  new  Regex( "$" , RegexOptions.Multiline);
40. Console.WriteLine( "r15 match count:"  + r15.Matches(i).Count); //2
41. Regex r16 =  new  Regex( "^Live for nothing,/r$/n^die for something$" , RegexOptions.Multiline);
42. Console.WriteLine( "r16 match count:"  + r16.Matches(i).Count); //1
43. // 对于一个多行字符串,在设置了 Multiline 选项之后, ^ $ 将出现多次匹配。
44.  
45. string  i =  "Live for nothing,die for something" ;
46. string  m =  "Live for nothing,die for some thing" ;
47. Regex r1 =  new  Regex(@ "/bthing/b" );
48. Console.WriteLine( "r1 match count:"  + r1.Matches(i).Count); //0
49. Regex r2 =  new  Regex(@ "thing/b" );
50. Console.WriteLine( "r2 match count:"  + r2.Matches(i).Count); //2
51. Regex r3 =  new  Regex(@ "/bthing/b" );
52. Console.WriteLine( "r3 match count:"  + r3.Matches(m).Count); //1
53. Regex r4 =  new  Regex(@ "/bfor something/b" );
54. Console.WriteLine( "r4 match count:"  + r4.Matches(i).Count); //1
55. ///b 通常用于约束一个完整的单词
56.  
 
(4) 重复描述字符
重复描述字符 是体现 C# 正则表达式 很好很强大 的地方之一:
{n} 
匹配前面的字符 n
{n,} 
匹配前面的字符 n 次或多于 n
{n,m} 
匹配前面的字符 n m
匹配前面的字符 0 1
匹配前面的字符 1 次或多于 1
匹配前面的字符 0 次或式于 0
以下提供一些简单的示例:
1.    string  x =  "1024" ;
2.    string  y =  "+1024" ;
3.    string  z =  "1,024" ;
4.    string  a =  "1" ;
5.    string  b= "-1024" ;
6.    string  c =  "10000" ;
7.    Regex r =  new  Regex(@ "^/+?[1-9],?/d{3}$" );
8.    Console.WriteLine( "x match count:"  + r.Matches(x).Count); //1
9.    Console.WriteLine( "y match count:"  + r.Matches(y).Count); //1
10. Console.WriteLine( "z match count:"  + r.Matches(z).Count); //1
11. Console.WriteLine( "a match count:"  + r.Matches(a).Count); //0
12. Console.WriteLine( "b match count:"  + r.Matches(b).Count); //0
13. Console.WriteLine( "c match count:"  + r.Matches(c).Count); //0
14. // 匹配 1000 9999 的整数。
 
(5) 择一匹配  
C#
正则表达式中的 (|) 符号似乎没有一个专门的称谓,姑且称之为 择一匹配 吧。事实上,像 [a-z] 也是一种择一匹配,只不过它只能匹配单个字符,而 (|) 则提供了更大的范围, (ab|xy) 表示匹配 ab 或匹配 xy 。注意 “|” “()” 在此是一个整体。下面提供一些简单的示例:
 
1.    string  x =  "0" ;
2.    string  y =  "0.23" ;
3.    string  z =  "100" ;
4.    string  a =  "100.01" ;
5.    string  b =  "9.9" ;
6.    string  c =  "99.9" ;
7.    string  d =  "99." ;
8.    string  e =  "00.1" ;
9.    Regex r =  new  Regex(@ "^/+?((100(.0+)*)|([1-9]?[0-9])(/./d+)*)$" );
10. Console.WriteLine( "x match count:"  + r.Matches(x).Count); //1
11. Console.WriteLine( "y match count:"  + r.Matches(y).Count); //1
12. Console.WriteLine( "z match count:"  + r.Matches(z).Count); //1
13. Console.WriteLine( "a match count:"  + r.Matches(a).Count); //0
14. Console.WriteLine( "b match count:"  + r.Matches(b).Count); //1
15. Console.WriteLine( "c match count:"  + r.Matches(c).Count); //1
16. Console.WriteLine( "d match count:"  + r.Matches(d).Count); //0
17. Console.WriteLine( "e match count:"  + r.Matches(e).Count); //0
18. // 匹配 0 100 的数。最外层的括号内包含两部分 “(100(.0+)*)” “([1-9]?[0-9])(/./d+)*” ,这两部分是 “OR” 的关系,即正则表达式引擎会先尝试匹配 100 ,如果失败,则尝试匹配后一个表达式(表示 [0,100) 范围中的数字)。
(6) 特殊字符的匹配  
下面提供一些简单的示例:
 
1.    string  x =  "//" ;
2.    Regex r1 =  new  Regex( "^$" );
3.    Console.WriteLine( "r1 match count:"  + r1.Matches(x).Count); //1
4.    Regex r2 =  new  Regex(@ "^//$" );
5.    Console.WriteLine( "r2 match count:"  + r2.Matches(x).Count); //1
6.    Regex r3 =  new  Regex( "^//$" );
7.    Console.WriteLine( "r3 match count:"  + r3.Matches(x).Count); //0
8.    // 匹配 “/”
9.     
10. string  x =  "/"" ;
11. Regex r1 =  new  Regex( "^/"$" );
12. Console.WriteLine( "r1 match count:"  + r1.Matches(x).Count); //1
13. Regex r2 =  new  Regex(@ "^""$" );
14. Console.WriteLine( "r2 match count:"  + r2.Matches(x).Count); //1
15. // 匹配双引号
(7) 组与非捕获组  
以下提供一些简单的示例:
 
1.    string  x =  "Live for nothing,die for something" ;
2.    string  y =  "Live for nothing,die for somebody" ;
3.    Regex r =  new  Regex(@ "^Live ([a-z]{3}) no([a-z]{5}),die /1 some/2$" );
4.    Console.WriteLine( "x match count:"  + r.Matches(x).Count); //1
5.    Console.WriteLine( "y match count:"  + r.Matches(y).Count); //0
6.    // 正则表达式引擎会记忆 “()” 中匹配到的内容,作为一个 ,并且可以通过索引的方式进行引用。表达式中的 “/1” ,用于反向引用表达式中出现的第一个组,即粗体标识的第一个括号内容, “/2” 则依此类推。
7.     
8.    string  x =  "Live for nothing,die for something" ;
9.    Regex r =  new  Regex(@ "^Live for no([a-z]{5}),die for some/1$" );
10. if  (r.IsMatch(x))
11. {
12.     Console.WriteLine( "group1 value:"  + r.Match(x).Groups[1].Value); // 输出: thing
13. }
14. // 获取组中的内容。注意,此处是 Groups[1] ,因为 Groups[0] 是整个匹配的字符串,即整个变量 x 的内容。
15.  
16. string  x =  "Live for nothing,die for something" ;
17. Regex r =  new  Regex(@ "^Live for no(?<g1>[a-z]{5}),die for some/1$" );
18. if  (r.IsMatch(x))
19. {
20.     Console.WriteLine( "group1 value:"  + r.Match(x).Groups[ "g1" ].Value); // 输出: thing
21. }
22. // 可根据组名进行索引。使用以下格式为标识一个组的名称 (?<groupname>…)
23.  
24. string  x =  "Live for nothing nothing" ;
25. Regex r =  new  Regex(@ "([a-z]+) /1" );
26. if  (r.IsMatch(x))
27. {
28.     x = r.Replace(x,  "$1" );
29.     Console.WriteLine( "var x:"  + x); // 输出: Live for nothing
30. }
31. // 删除原字符串中重复出现的 “nothing” 。在表达式之外,使用 “$1” 来引用第一个组,下面则是通过组名来引用:
32. string  x =  "Live for nothing nothing" ;
33. Regex r =  new  Regex(@ "(?<g1>[a-z]+) /1" );
34. if  (r.IsMatch(x))
35. {
36.     x = r.Replace(x,  "${g1}" );
37.     Console.WriteLine( "var x:"  + x); // 输出: Live for nothing
38. }
39.  
40. string  x =  "Live for nothing" ;
41. Regex r =  new  Regex(@ "^Live for no(?:[a-z]{5})$" );
42. if  (r.IsMatch(x))
43. {
44.     Console.WriteLine( "group1 value:"  + r.Match(x).Groups[1].Value); // 输出: ( )
45. }
46. // 在组前加上 “?:” 表示这是个 非捕获组 ,即引擎将不保存该组的内容。
47.  
(8) 贪婪与非贪婪  
正则表达式的引擎是贪婪,只要模式允许,它将匹配尽可能多的字符。通过在 重复描述字符 *,+ )后面添加 “?” ,可以将匹配模式改成非贪婪。请看以下示例:
 
1.    string  x =  "Live for nothing,die for something" ;
2.    Regex r1 =  new  Regex(@ ".*thing" );
3.    if  (r1.IsMatch(x))
4.    {
5.        Console.WriteLine( "match:"  + r1.Match(x).Value); // 输出: Live for nothing,die for something
6.    }
7.    Regex r2 =  new  Regex(@ ".*?thing" );
8.    if  (r2.IsMatch(x))
9.    {
10.     Console.WriteLine( "match:"  + r2.Match(x).Value); // 输出: Live for nothing
11. }
(9) 回溯与非回溯  
使用 “(?>…)” 方式进行非回溯声明。由于正则表达式引擎的贪婪特性,导致它在某些情况下,将进行回溯以获得匹配,请看下面的示例:
 
1.    string  x =  "Live for nothing,die for something" ;
2.    Regex r1 =  new  Regex(@ ".*thing," );
3.    if  (r1.IsMatch(x))
4.    {
5.        Console.WriteLine( "match:"  + r1.Match(x).Value); // 输出: Live for nothing,
6.    }
7.    Regex r2 =  new  Regex(@ "(?>.*)thing," );
8.    if  (r2.IsMatch(x)) // 不匹配
9.    {
10.     Console.WriteLine( "match:"  + r2.Match(x).Value);
11. }
12. // r1 中, “.*” 由于其贪婪特性,将一直匹配到字符串的最后,随后匹配 “thing” ,但在匹配 “,” 时失败,此时引擎将回溯,并在 “thing,” 处匹配成功。
13. // r2 中,由于强制非回溯,所以整个表达式匹配失败。
14.  
(10) 正向预搜索、反向预搜索  
正向预搜索声明格式:正声明 “(?=…)” ,负声明 “(?!...)” ,声明本身不作为最终匹配结果的一部分,请看下面的示例:反向预搜索声明格式:正声明 “(?<=)” ,负声明 “(?<!)” ,声明本身不作为最终匹配结果的一部分,请看下面的示例:
 
1.    string  x =  "1024 used 2048 free" ;
2.    Regex r1 =  new  Regex(@ "/d{4}(?= used)" );
3.    if  (r1.Matches(x).Count==1)
4.    {
5.        Console.WriteLine( "r1 match:"  + r1.Match(x).Value); // 输出: 1024
6.    }
7.    Regex r2 =  new  Regex(@ "/d{4}(?! used)" );
8.    if  (r2.Matches(x).Count==1)
9.    {
10.     Console.WriteLine( "r2 match:"  + r2.Match(x).Value);  // 输出: 2048
11. }
12. //r1 中的正声明表示必须保证在四位数字的后面必须紧跟着 “ used” r2 中的负声明表示四位数字之后不能跟有 “ used”
(11) 十六进制字符范围  
正则表达式中,可以使用 "/xXX" "/uXXXX" 表示一个字符( "X" 表示一个十六进制数)形式字符范围:  
/xXX      
编号在 0 255 范围的字符,比如:空格可以使用 "/x20" 表示。  
/uXXXX  
任何字符可以使用 "/u" 再加上其编号的 4 位十六进制数表示,比如:汉字可以使用 “[/u4e00-/u9fa5]” 表示。
1.    string  x =  "used:1024 free:2048" ;
2.    Regex r1 =  new  Regex(@ "(?<=used:)/d{4}" );
3.    if  (r1.Matches(x).Count==1)
4.    {
5.        Console.WriteLine( "r1 match:"  + r1.Match(x).Value); // 输出: 1024
6.    }
7.    Regex r2 =  new  Regex(@ "(?<!used:)/d{4}" );
8.    if  (r2.Matches(x).Count==1)
9.    {
10.     Console.WriteLine( "r2 match:"  + r2.Match(x).Value); // 输出: 2048
11. }
12. //r1 中的反向正声明表示在 4 位数字之前必须紧跟着 “used:” r2 中的反向负声明表示在 4 位数字之前必须紧跟着除 “used:” 之外的字符串。
13.  
 
(12) [0,100] 的比较完备的匹配
下面是一个比较综合的示例,对于匹配 [0,100] ,需要特殊考虑的地方包括
*00
合法, 00. 合法, 00.00 合法, 001.100 合法
*
空字符串不合法,仅小数点不合法,大于 100 不合法
*
数值是可带后缀的,如 “1.07f” 表示该值为一个 float 类型(未考虑)
 
1.    Regex r =  new  Regex(@ "^/+?0*(?:100(/.0*)?|(/d{0,2}(?=/./d)|/d{1,2}(?=($|/.$)))(/./d*)?)$" );
2.    string  x =  "" ;
3.    while  ( true )
4.    {
5.        x = Console.ReadLine();
6.         if  (x !=  "exit" )
7.        {
8.             if  (r.IsMatch(x))
9.            {
10.             Console.WriteLine(x +  " succeed!" );
11.         }
12.          else
13.         {
14.             Console.WriteLine(x +  " failed!" );
15.         }
16.     }
17.      else
18.     {
19.          break ;
20.     }
21. }
22.  
(13) 精确匹配有时候是困难的
有些需求要做到精确匹配比较困难,例如:日期、 Url Email 地址等,其中一些你甚至需要研究一些专门的文档写出精确完备的表达式,对于这种情况,只能退而求其次,保证比较精确的匹配。例如对于日期,可以基于应用系统的实际情况考虑一段较短的时间,或者对于像 Email 的匹配,可以只考虑最常见的形式。
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值