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 的匹配,可以只考虑最常见的形式。 |
C#正则表达式整理备忘
最新推荐文章于 2024-09-22 16:08:33 发布