http://www.crifan.com/summary_regular_expression_csharp_python/
此处总结一下,关于正则表达式的相关知识。
此文目的是总结一下正则表达式的基本语法,以及总结个人接触过的一些不同语言的实现中需要注意的地方,以及相关经验。
【正则表达式的最简介】
正则表达式,英文叫做Regular Expression,一般缩写为regex或regexp。
正则表达式,简单说,就是一组规则,用于实现字符串的查找,匹配,以实现关于字符串的相关操作,比如替换,删除等。
很多语言目前都已实现了对应的正则表达式的支持。
目前个人已知的有,Python脚本语言,C#语言,PHP语言,Notepad++软件的查找/替换功能中。
学会了正则表达式后,很多常见的文字,字符串的处理,就简单的多了,或者可以更加高效地实现功能,实现更加复杂的操作了。
【正则表达式的基本规则】
下面的规则,是从Python的说明文档中翻译过来的。
网上也有类似的总结,此处只是觉得这个解释更全,更精确,所以采用这部分的内容为基准。
其他不同语言所实现的正则表达式,语法上,也许个别会有不同,但是基本语法和含义,都是通用的。
下表,以供借鉴。
字符匹配的规则:
特殊字符 | 等价于 | 含义解释 | 提示 |
. | 表示任意字符(除了换行符\n以外的任意单个字符) | ||
^ | 表示字符串的开始 | ||
$ | 表示字符串行末或换行符之前 | ||
* | {0,无穷多个} | 0或多个前面出现的正则表达式 | 贪婪原则,即尽量匹配尽可能多个 |
+ | {1,无穷多个} | 1或多个前面出现的正则表达式 | 贪婪原则,即尽量匹配尽可能多个 |
? | {0,1} | 0或1个前面出现的正则表达式 | 贪婪原则,即尽量匹配尽可能多个 |
*?,+?,?? | 使*,+,?尽可能少的匹配 | 最少原则 | |
{m} | 匹配m个前面出现的正则表达式 | ||
{m,n} | 匹配最少m个,最多n个前面出现的正则表达式 | 贪婪原则,即尽量匹配尽可能多个 | |
{m,n}? | 匹配最少m个,最多n个前面前出现的 | 最少原则 | |
\ | 后接那些特殊字符,表示该字符;或者后接已经定义好的特殊含义的序列 | 对于已经定义好的特殊序列,下面会详细解释。 | |
[] | 指定所要匹配的字符集,可以列出单个字符;或者是一个字符范围,起始和结束字符之间用短横线-分割; | ||
| | A|B,其中A和B可以是任意正则表达式,其中也支持更多的抑或A|B|C|… | ||
(……) | 匹配括号内的字符串 | 实现分组功能,用于后期获得对应不同分组中的字符串 |
已定义的字符序列的含义:
特殊序列/已定义的字符含义 | 等价于 | 含义解释 | 提示 |
\数字 | 表示前面用括号()括起来的某个组group | ||
\A | 表示字符串的开始 | ||
\b | 匹配空字符,但只是一个单词word的开始或者结束的空字符 | ||
\B | \b含义取反 | 匹配空字符,但只是,一个单词word的,除了开始或者结束位置的,的空字符 | |
\d | [0-9] | 匹配单个数字(0到9中的某个数字) | |
\D | [0-9]的取反 | 非数字的单个字符,即除了0-9之外的任意单个字符 | |
\s | [ \t\n\r\f\v] | 匹配单个空白字符,包括空格,水平制表符\t,回车\r,换行\n,换页\f,垂直制表符\v | |
\S | \s的含义取反 | 匹配非空白字符之外的单个字符 | |
\w | [a-zA-Z0-9_] | 匹配单个的任何字符,数字,下划线 | |
\W | \w的含义取反 | 匹配单个的,非字母数字下划线之外的字符 | |
\Z | 匹配字符串的末尾 |
【一些总结和注意事项】
1.关于贪婪原则和最少原则
星号*,加号+,问号?,{m,n},都是属于贪婪原则,即在满足这些条件的情况下,尽可能地匹配多个。
而对应的后面加上一个问号?,变成:
*?, +?, ??, {m,n}?就变成了最少原则,即,在满足前面的条件的情况下,尽量少地匹配。
其中??,个人很少用。
而最常用的是 .+?,表示任意字符,最少是1个,然后后面匹配尽量少的所出现的字符。
2.反斜杠\
在正则表达式中,反斜杠\后面接一些特殊字符,表示该特殊字符,这些特殊是,上面所说过的:
.,^,$,*,+,?
对应的是:
\.,\^,\$,\*,\+,\?
以及反斜杠自己:
\\
其中如果是在中括号[]内,反斜杠加上对应的中括号[]和短横线-,即:
\[,\],\-
分别表示对应的字符本身。
3.上尖括号^
在中括号之外,表示字符的开始;
在中括号之内,表示取反,比如常见的[^0-9]
比如[^5]表示除了数字5之外的所有字符。
尤其特别的是[^^]表示除了上尖括号字符本身之外的所有字符。
4. 中括号内的+,*,(,)
中括号内的加号+,星号*,括号(,)表示对应字符本身,就不是特殊字符了。
【正则表达式的特点】
- 入门相对不难,但是能熟练,高效的利用其功能,还是不容易的。
【Python中的正则表达式:re模块】
优点:
1.python中字符串的表示,单引号和双引号,都是支持的。
所以对于字符串中,有双引号的,可以在写字符串最外层用单引号括起来,而不需要用反斜杠了。
反之,如果需要表示的其中包括单引号,那么最外层用双引号,所以,还是很方便的。
2.对于匹配多个字符串的时候,好像不能加括号分组的,如果加括号分组了,那么只能匹配单个一个group就结束了。对应的要匹配多个字符串,好像只能使用findall。
这部分内容,有空再好好总结一下。
【C#中的正则表达式:Regex类】
后来找到了,微软官方关于正则表达式知识的介绍,其中就有常用缩写所表示的含义:
优点:
1.可以一次性的即搜索多个匹配的整个的字符串,同时又可以一次性地,对于每个字符串,在给定Regex的时候,就分组group,然后得到macthes之后,foreach处理每个match,已经可以得到对应的匹配的结果,可以使用不同group的值了。还是很方便的。
注意事项:
1.正则表达式,是用字符串前面加上@字符来表示的。
2.双引号‘“’这个符号的表示是用两个双引号。
由于C#中本身字符串是双引号表示的,所以正则表达式中的双引号,就特殊了,是需要用两个双引号,表示对应的双引号这个字符的,而不是反斜杠加上双引号来表示双引号这个字符,这点,觉得还是很特殊的,需要注意一下。
关于C#中的Regex使用心得和注意事项,感兴趣的可以去看:
【C#和Python中关于正则表达式方面的对比】
1. 带名字的group
python和C#中的正则表达式,都支持带名字的group,即named group,关于具体的语法,两者有些微的区别:
Python: (?P<groupName>xxx)
C#: (?<groupName>xxx)
即Python中,named group的语法,比C#中,多了个P字母作为开头。
2.正则表达式字符串的开头标记字母
Python:r,比如r“(.+?)”
C#:@,比如@“(.+?)”
3.关于引用已捕获的带名字的组(back reference named group)
正则表达式的逻辑中,支持在写模式字符串中,引用前面已经过通过括号括起来的,带名字的组。
Python中的语法是:
C#中的语法是:
直接给出示例代码:
Python中关于引用named group的用法示例(记得要import re;):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#------------------------------------------------------------------------------
def
testBackReference():
# back reference (?P=name) test
backrefValidStr
=
'"group":0,"iconType":"NonEmptyDocumentFolder","id":"9A8B8BF501A38A36!601","itemType":32,"name":"released","ownerCid":"9A8B8BF501A38A36"'
;
backrefInvalidStr
=
'"group":0,"iconType":"NonEmptyDocumentFolder","id":"9A8B8BF501A38A36!601","itemType":32,"name":"released","ownerCid":"987654321ABCDEFG"'
;
backrefP
=
r
'"group":\d+,"iconType":"\w+","id":"(?P<userId>\w+)!\d+","itemType":\d+,"name":".+?","ownerCid":"(?P=userId)"'
userId
=
"";
foundBackref
=
re.search(backrefP, backrefValidStr);
print
"foundBackref="
,foundBackref;
# foundBackref= <_sre.SRE_Match object at 0x02B96660>
if
(foundBackref):
userId
=
foundBackref.group(
"userId"
);
print
"userId="
,userId;
# userId= 9A8B8BF501A38A36
print
"can found userId here"
;
foundBackref
=
re.search(backrefP, backrefInvalidStr);
print
"foundBackref="
,foundBackref;
# foundBackref= None
if
(
not
foundBackref):
print
"can NOT found userId here"
;
return
;
|
C#关于引用named group的示例代码(记得要using System.Text.RegularExpressions;):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
void
testBackReference()
{
// back reference \k<name> test
string
backrefValidStr =
"\"group\":0,\"iconType\":\"NonEmptyDocumentFolder\",\"id\":\"9A8B8BF501A38A36!601\",\"itemType\":32,\"name\":\"released\",\"ownerCid\":\"9A8B8BF501A38A36\""
;
string
backrefInvalidStr =
"\"group\":0,\"iconType\":\"NonEmptyDocumentFolder\",\"id\":\"9A8B8BF501A38A36!601\",\"itemType\":32,\"name\":\"released\",\"ownerCid\":\"987654321ABCDEFG\""
;
string
backrefP =
@"""group"":\d+,""iconType"":""\w+"",""id"":""(?<userId>\w+)!\d+"",""itemType"":\d+,""name"":"".+?"",""ownerCid"":""\k<userId>"""
;
string
userId =
""
;
Regex backrefValidRx =
new
Regex(backrefP);
Match foundBackref;
foundBackref = backrefValidRx.Match(backrefValidStr);
if
(foundBackref.Success)
{
// can found the userId
userId = foundBackref.Groups[
"userId"
].Value;
MessageBox.Show(
"can found the userId !"
);
}
foundBackref = backrefValidRx.Match(backrefInvalidStr);
if
(foundBackref.Success)
{
// can NOT found the userId
}
else
{
MessageBox.Show(
"can NOT found the userId !"
);
}
}
|
4.关于向前匹配(prev match)和向后匹配(post match),以及向前一定不要匹配(prev non-match),和向后一定不要匹配(post non-match)
Python中的语法是:
C#的语法是:
直接给出相关示例代码:
Python中关于前向,后向,匹配,非匹配等的示例代码(记得要import re;):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#------------------------------------------------------------------------------
def
testPrevPostMatch():
# post match: (?=xxx)
# post non-match: (?!xxx)
# prev match: (?<=xxx)
# prev non-match: (?<!xxx)
#note that input string is:
#src=\"http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA\"
qqPicUrlStr
=
'src=\\"http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA\\"'
;
qqPicUrlInvalidPrevStr
=
'1234567http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA\\"'
;
qqPicUrlInvalidPostStr
=
'src=\\"http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA123'
;
qqPicUrl
=
"";
foundPrevPost
=
re.search(canFindPrevPostP, qqPicUrlStr);
print
"foundPrevPost="
,foundPrevPost;
#
if
(foundPrevPost):
qqPicUrl
=
foundPrevPost.group(
"qqPicUrl"
);
print
"qqPicUrl="
,qqPicUrl;
# qqPicUrl=http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA
print
"can found qqPicUrl here"
;
foundInvalidPrev
=
re.search(canFindPrevPostP, qqPicUrlInvalidPrevStr);
print
"foundInvalidPrev="
,foundInvalidPrev;
# foundInvalidPrev= None
if
(
not
foundInvalidPrev):
print
"can NOT found qqPicUrl here"
;
foundInvalidPost
=
re.search(canFindPrevPostP, qqPicUrlInvalidPostStr);
print
"foundInvalidPost="
,foundInvalidPost;
# foundInvalidPost= None
if
(
not
foundInvalidPost):
print
"can NOT found qqPicUrl here"
;
return
;
|
C#中关于前向,后向,匹配,非匹配等的示例代码(记得要using System.Text.RegularExpressions;):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
void
testPrevPostMatch()
{
//http://msdn.microsoft.com/en-us/library/bs2twtah(v=vs.71).aspx
// post match: (?=xxx)
// post non-match: (?!xxx)
// prev match: (?<=xxx)
// prev non-match: (?<!xxx)
//src=\"http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA\"
string
qqPicUrlStr =
"src=\\\"http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA\\\""
;
string
qqPicUrlInvalidPrevStr =
"12345678http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA\\\""
;
string
qqPicUrlInvalidPostStr =
"src=\\\"http://b101.photo.store.qq.com/psb?/V10ppwxs00XiXU/5dbOIlYaLYVPWOz*1nHYeSFq09Z5rys72RIJszCsWV8!/b/YYUOOzy3HQAAYqsTPjz7HQAA1234"
;
string
qqPicUrl =
""
;
Regex prevPostRx =
new
Regex(canFindPrevPostP);
Match foundPrevPost = prevPostRx.Match(qqPicUrlStr);
if
(foundPrevPost.Success)
{
qqPicUrl = foundPrevPost.Groups[
"qqPicUrl"
].Value;
MessageBox.Show(
"can found the qqPicUrl !"
);
}
Match foundInvalidPrev = prevPostRx.Match(qqPicUrlInvalidPrevStr);
if
(!foundInvalidPrev.Success)
{
MessageBox.Show(
"can NOT found the qqPicUrl !"
);
}
Match foundInvalidPost = prevPostRx.Match(qqPicUrlInvalidPostStr);
if
(!foundInvalidPost.Success)
{
MessageBox.Show(
"can NOT found the qqPicUrl !"
);
}
}
|