您的位置:首页 > 其它

正则表达式学习总结

2013-12-02 22:35 281 查看
正则表达式学习总结
有这样一个需求,根据一个网址提取出这个网站里面你需要的一些内容。比如,有一个网站的网址为http://search.51job.com/job/46629381,c.html,需要提取出这个网站页面所有的职位名称或其它信息。在C#中,我们可以根据它所提供的一些类来完成对这个页面的访问,如WebClient类。它可以把这个网站的页面内容以字符串的方式返回给调用者,这其中包含HTML标签。那我们该怎样从这一大堆的字符串中得到我们想要的职位信息呢?如果用处理简单字符串的方式来处理这个长字符串,那实在太让人崩溃了。

这时,正则表达式的作用就突显出来了。正则表达式就是用来进行文本处理的技术,是和语言无关的,在所有语言都有正则表达式的实现。一个正则表达式是由普通字符和特殊字符(也称元字符)组成的字符串模式。我们要在一个待查找的字符串中,寻找与该字符串模式相匹配的子字符串。正则表达式就是一个匹配的模板,它主要对字符串进行查找、提取和替换。

正则表达式的元字符主要有如下:

l .:匹配除\n之外的任何单个字符

l [ ] :匹配括号中的任何一个字符,如果是ASCII连续的字符,可以使用-连接起来

l | :将两个匹配条件进行逻辑“或”运算,注意或的优先级最低

l ():改变优先级,提取内容到组中

l *:匹配前面紧临的子表达式0至多次

l + :匹配前面紧临的子表达式1至多次

l ? :匹配前面紧临的子表达式0至1次

l {n} :匹配前面紧临的子表达式出现n次

l {n,} :匹配前面紧临的子表达式出现至少n次

l {n,m} :匹配前面紧临的子表达式出现最少n次且最多m次

l ^:匹配开始,用在中括号中表示非,发音:hat

l $ :匹配行结束符,发音:dollor

l 严格匹配时一定要加上^与$,其它时候不用

l 注意这些简写表达式是不考虑转义符的,如果写在C#中要注意使用@或\\表示一个\

l \d:代表一个数字,等同于[0-9]

l \D:代表非数字,等同于[^0-9]

l \s:代表换行符、制表符、空格等空白字符

l \S:代表非空白字符

l \w:匹配字母、数字、下划线、汉字,即能组成单词的字符,等同于[a-zA-Z0-9_汉字]

l \W:非\w ,等同于[^\w]

l d:digital;s:space;w:word;大写就是“非”

以上元字符我们不需要花时间去记,只需要在用到的时候查阅即可。使用得多了,我们自然而然就会记住。

在写正则表达式时,要注意不要期望写出一个万能的表达式来,只要能够解决当前的问题即可。并且表达式越复杂,性能越慢;表达式越简单,性能越高。

在C#中运用正则表达式的类是Regex类,它位于System.Text.RegularExpression命名空间中。写正则表达式时,直接写成字符串即可。

例如:假如我们要匹配一个给定字符串是否是IP地址,可用如下方式完成。

string ip =
"192.168.1.101";
Regexreg1 =
new Regex(@"^\d{3}(\.\d{0,3}){3}$");

Console.WriteLine(reg1.IsMatch(ip));
在以上示例中,一开始数字字符要出现3次,所以开始为^\d{3} 。然后一个点外加3个数字字符这个组合要连续出现3次,所以匹配字符串的后面为(\.\d{0,3}){3}。如果在字符串中有与给定表达式相匹配的项,则IsMatch方法返回true,否则为False。

如果想提取一个字符串中与给定表达式相匹配的子字符串,则需要调用Regex的Match方法,这个方法返回一个Match类型的对象。在这个Match对象的Value属性中保存有提取出的子字符串,但Match方法只能对字符串进行一次匹配。如果想提取出字符串中与表达式相匹配的所有字符串,则要用Mathes方法,这个方法返回一个Match对象的集合MatchCollection,这个集合中的每个Match对象都有一个Groups属性,这个Groups属性也是一个集合,它存储的是匹配到的字符串中你想提取的部分子字符串。在正则表达式中,我们用小括号把想提取的部分字符串括起来,这样在匹配正则表达式的整个字符串时,会把我们想提取的项添加到Groups集合中,默认匹配到的字符串本身也是我们要提取的部分,它占据Groups集合中的第1个位置(索引为0)。所以在正则表达式中如果有多个提取项,则要从第2个位置(索引为1)开始提取。如提取网页信息的需求中,要先查看网页源码,找到需要提取的部分,找出这部分HTML代码与其它地方的不同之处,然后根据这个不同再来写正则表达式。通过查看网页源码,我们发现每个职位名称都包含在一个<a></a>超链接标签中,并且这些标签中都有一部分字符串为class=”jobname”,我们就可以根据这一大特点写出当前需求可用的正则表达式。具体代码如下:

static void Main(string[] args)
{
string path = "【上海IT管理计算机软件招聘,求职】前程无忧.htm";
WebClient wc = new WebClient();
byte[] bt = wc.DownloadData(path);
string content = Encoding.Default.GetString(bt, 0,bt.Length);

Regexreg = new Regex("<a .*class=\"jobname\".*>(.*)</a>");
MatchCollection mc = reg.Matches(content);
Console.WriteLine("总共有职位{0}个:",mc.Count);
for(int i = 0; i < mc.Count; i++)
{
Console.WriteLine(mc[i].Groups[1]);
}
Console.ReadKey();
}

运行代码,总共提取出的职位有30个。

正则表达式的替换使用Regex的Replace方法。这个方法可以把匹配到的字符串替换为给定字符串。如果想对字符串中的提取组进行替换,则在给定的字符串中,用“$1”表示提取组中的第1个元素,用“$2”表示第2个元素,依此类推。并且把表示替换提取组的字符串与其它给定的字符串连接就可以完成组的替换。如:如果我们想将“2013年3月11日”显示为“2013-3-11”,就可以使用替换组的方式来完成。代码如下:

string date1 =
"2013年3月11日";
// 2013-3-11
string regex=
@"(\d+)年(\d+)月(\d+)日";
string res =
Regex.Replace(date1,regex, "$1-$2-$3");

在正则表达式中,还有个重要的概念就是贪婪模式和非贪婪模式。贪婪模式就是说如果一个字符串和它的子字符串都满足正则表达式,那么这个正则表达式一定会默认去匹配整个字符串,而不会去匹配它的子字符串。发生贪婪的前提是表达式中出现了*或+或{n,}这种不限制上限的元字符。在匹配这个表达式的时候,能多匹配一个字符就多匹配一个,绝不会去按照少的来匹配,直到最后一次匹配到+或*的右侧第一个字符为止。如果我们想禁止这种贪婪模式,则需要在*或+的后面加上一个?,这样该正则表达式就不会发生贪婪。
在实现正则表达式的类Regex中,匹配、提取和替换方法都有静态方法和非静态方法。如果正则表达式确定下来之后,不再改变,则使用静态方法;如果正则表达式的改变会比较多,则使用非静态方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: