我的.NET生活

活着便精彩!
随笔 - 41, 评论 - 680, 引用 - 66

导航

关于

标签

每月存档

最新留言

广告

 

前几天,一位好朋友问我这样一个问题:

?

有一份html文件,里面有很多的网址引用的是相对地址,比如说,需要把它改成绝对地址,例如www.codeproject.com/image/logo.gif />。由于源文件体积不小,因此需要一个快速而且资源占用不大的处理方法。

?

我当时的第一反应就是使用正则表达式,因为与其它方式,比如说直接处理字符串或者使用XmlReader/XmlWriter等相比,正则表达式的速度和资源占用都是最佳的。因此,仔细考虑之后,我写成了下面的代码:

?

using System;
using System.Text.RegularExpressions;
using System.IO;

class EvalDemo
{
    public static string GetResult(Match m)
    {
        return Regex.Replace(m.Value, @"[/]", @"http://www.codeproject.com/");
    }
}

class Demo
{
    public static void Main()
    {
        StreamReader reader=File.OpenText("source.txt");
        string source=reader.ReadToEnd();
        reader.Close();

        string reg=@"href\s*=\s*[""']?/";
        string result=Regex.Replace(source, reg, new MatchEvaluator(EvalDemo.GetResult));
        Console.WriteLine(result);
    }
}

?

其中,放置在同一目录下的source.txt文件保存有需要修改的html源文件,当然你也可以把它放在其它目录下,或者采用不同的方式来获得,例如通过HttpResponse来获取相含有该文件的流。

?

在打开该文件并读入内存后,我使用StreamReader.ReadToEnd方法获取了流内容的字符串表示,然后用正则表达式对这一字符串进行操作。也许你会问,直接通过查找把所有的href=”\替换成href=”www.codeproject.com\不可以吗?这样是可以的,但如果html代码变成了href=\那么就无法处理了,另外因为html允许在有效字符间留有空格,所以如果用户在html文件中把代码写成href =? \,那么你也必须把这种情况考虑在内(尽管不太会发生),这样你的string.Replace方法就会变得很复杂,而应用正式表达式来处理这一问题就会简单多了,请看下面这行代码:

?

string reg=@"href\s*=\s*[""']?/";

?

如果你此前没接触过正则表达式,那么可能会感到有些复杂。其实只要我把其中各项所代表的内容解释在下面,你就会发现其实正则表达式没什么神秘的:

?

字符

含义

\s

匹配一个空白字符,比如全角空格、半角空格、制表符等

*

表示它前面的项目(\s)可以有零个或多个匹配,也就是说这里既可以没有空格,也可以有多个空格

[]

匹配其中的单个字符

[“”’]

匹配这两个字符:双引号或者单引号。由于双引号在C#里有特殊含义,因此需要以两个双引号的形式来表示单个双引号

表示它前面的项目([“”’])可以有一个或多个匹配,与*的用法相似

?

有了上面的解释,再去看那段正则表达式是不是很简单了?其实就是要找一段类似href=”\的字符串,其中可能会含有一些空白字符或可选字符。好了,接着往下看。

?

string result=Regex.Replace(source, reg, new MatchEvaluator(EvalDemo.GetResult));

?

这是标准的正则表达式替换操作的用法,其中前两项参数的用意非常明确,而第三项参数比较特殊:在这里创建了一个MatchEvaluator委托的实例,并传入了一个回调方法——EvalDemo.GetResult的地址。为什么要这样设计呢?其实一般的正则表达式替换操作是不需要这样复杂的,你只需指定要替换的源,要替换的字符,以及替换后的字符即可,但在这个示例里情况很特殊——你无法确切获知要被替换的是什么字符!不是吗?可能是href=”\,也可能是href=’\,甚至可能是href?? =??? \,因此你需要通过一个回调函数来处理这个变化多端的字符串,在处理后传回处理结果,例如对于href=”\而言,处理结果将是href=”\www.codeproject.com,而href=’\的处理结果则是href=’\www.codeproject。理解了这一点以后,就请来看看这个简单有趣的回调方法:

?

class EvalDemo
{
??? public static string GetResult(Match m)
??? {
??????? return Regex.Replace(m.Value, @"[/]", @"http://www.codeproject.com/");
??? }
}

?

在这里,回调方法其实是自定义的EvalDemo类的静态方法,该方法接受一个Match类实例,通过Match.Value可以获得需要处理的字符串,然后对该字符串加以处理即可。因此,在GetResult方法里,我用了一个最基本的正则表达式替换操作,查找所有需要处理的字符串中的/(斜杠)字符,把它替换成http://www.codeproject.com,然后返回结果。这样,Main中的替换操作便获得了所需的第三个参数,替换操作可以进行了。

?

最后,为了演示方便,我把最终结果(即修改后的html文件内容)打印到Console上面。你可以自己选择是否打印,或者保存到文件中。

?

OK,一个不太复杂的正则表达式的应用就讲解到这里了,希望能通过这篇文章带你进入正则表达式的大门。如果你对本文有任何意见或看法,欢迎提出来!笑脸

打印 | 张贴于 2004-02-25 18:32:00 | Tag:暂无标签

留言反馈

#回复: Simple & Funny——用正则表达式处理html文档 编辑
2007-12-18 05:13:00 | [匿名:runescape gold]
#re: Simple & Funny——用正则表达式处理html文档 编辑
OK!GOOD!
2006-05-24 19:22:00 | [匿名:正则]
#re: Simple & Funny——用正则表达式处理html文档 编辑
请问怎么在C#里检测一个字符串是否和一个正则表达式相匹配?
比如检测E-Mail地址
2005-01-18 10:00:00 | [匿名:Sandheart]
#re: Simple & Funny——用正则表达式处理html文档 编辑
我基址和相对网址相叠加用URI类的
2005-01-05 14:18:00 | [匿名:fangjing]
#re: Simple & Funny——用正则表达式处理html文档 编辑
11111111111111111111111111111
2004-12-27 12:20:00 | [匿名:2222222]
#re: Simple & Funny——用正则表达式处理html文档 编辑
请问有办法去掉String字符中的html代码吗?
2004-12-24 16:48:00 | [匿名:peng]
#re: Simple & Funny——用正则表达式处理html文档 编辑
good
2004-09-09 23:58:00 | [匿名:laily]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
to JKou:

目前有几家第三方公司(机构)已经做了相关的努力,如MONO、DotGNU等。它们的实现效果各有千秋。
2004-04-14 11:39:00 | [匿名:musicland]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
在linux下可以应用.NET了吗?
2004-04-14 11:34:00 | [匿名:JKou]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
呵呵,学习……
2004-03-27 14:28:00 | [匿名:小春]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
呵呵,,,这个本来就是.net框架中的咯
不懂的怎么说win32api了
多跟做这学这点。哈哈
支持支持
2004-03-01 08:32:00 | [匿名:雨生]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
不知道Java中有没有对正则表达式处理的API,
有用过的吗?
2004-02-29 22:29:00 | [匿名:wangfeng]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
hi 小峰:

您说的这一API我的确未曾接触,不过我个人的习惯是尽可能地减少对Win32 API的依赖,因为这是在开发.NET,我会经常把.NET应用拿到Linux下去的。

不过您提的这一点的确很重要,大家如果对跨平台移植不感兴趣的话可以应用pinvoke来调用UrlCombine。

BTW:UrlCombine在哪个dll中?
2004-02-27 10:46:00 | [匿名:musicland]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
SO GOOD
2004-02-26 08:31:00 | [匿名:KAVANA]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
谢谢
2004-02-26 06:18:00 | [匿名:lonelystranger]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
To musicland:
代码空间只能大家想办法了:(,我没有办法提供给大家的:'(
2004-02-25 22:00:00 | [匿名:开心就好]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
呵呵,还真得问问开心,以后写文章配代码的朋友肯定不在少数,博客堂真的需要一个上传空间了:)
2004-02-25 21:50:00 | [匿名:musicland]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
community request:
usersample.joycode.com
2004-02-25 21:45:00 | [匿名:Johnny Hu]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
博客堂的网友们总是让我受益匪浅!!!
2004-02-25 21:08:00 | [匿名:开心就好]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
又是Johnny Hu帮了我的忙,看来我们俩前店后厂搭配得挺好不是吗?:B

大家如有兴趣,请到Johnny Hu所给出地址下载源码:)
2004-02-25 20:54:00 | [匿名:musicland]
#回复: Simple & Funny——用正则表达式处理html文档 编辑
学习中。。。
2004-02-25 20:06:00 | [匿名:moslem]
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode.MVC引擎 0.5.2.0