﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-CONAN ZONE-文章分类-其他技术</title><link>http://www.blogjava.net/conans/category/32372.html</link><description>你越挣扎我就越兴奋</description><language>zh-cn</language><lastBuildDate>Sun, 25 Oct 2009 05:43:44 GMT</lastBuildDate><pubDate>Sun, 25 Oct 2009 05:43:44 GMT</pubDate><ttl>60</ttl><item><title>web会话状态维持</title><link>http://www.blogjava.net/conans/articles/299650.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Sun, 25 Oct 2009 02:59:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/299650.html</guid><description><![CDATA[如果你对以下问题感兴趣但是又不能确切的回答，你就应该阅读此文．
<br />
1.Session是什么？
<br />
2.Cookie又是什么？
<br />
3.如果完全禁用了Cookies，Session还起作用吗？
<br />
4.为什么有的网站登录一次以后就不用再登录?
<br />
5.ASP中的Session是否依赖Cookie?
<br />
6.JSP中的Session是否依赖Cookie?
<br />
7.ASP.NET中的Session又是怎么回事?
<br />
<br />
下面将详细的讲述会话状态的维持,看完之后你应该可以回答上面的几个问题了
<br />
1.Session和Cookie的由来
<br />
这里我不区分Cookie和Cookies,只是一个复数形式而已.我们都知道http是无状态的协议,就是说每次请求都是分开的，服务器根本不
知道两次请求是否是同一个人,如果我们的内容是完全公开的,也就是所有内容谁都可以看(比如sina的新闻),这种情况呀根本就没有必要知道两次请求是不
是同一个.但是大部分情况下我们不希望这样,我们希望只有会员登录之后才能访问(所有的论坛几乎都是这样).而其他人不允许他们反问,于是便要知道每次请
求的是不是同一个人,这就是会话,也就是一个Session,而且这个Session是以Cookie为基础的,Cookie最才是网景公司提出的,也叫
小甜饼.
<br />
服务器端对每个请求维持一个会话,并且有一个唯一的SessionID.如果客户端没有禁用Cookie的话,客户第一次请求的时候这个ID会
写到客户端的硬盘上(不相信?看一下文件夹C:\Documents and Settings\UserName\Local
Settings\Temporary Internet Files
下的Cookie文件,都是文本文件).以后你每次请求的时候都会加上这个ID值,服务器端就可以知道是不是同一个请求了.如果还不相信的话,你可以这样
做个试验:
<br />
1.选择一个你要用用户名登录的网站(最好是ASP的,如论坛).
<br />
2.先正常登录一遍,确定可以登录,再把浏览器关了)
<br />
3.选择Internet选项(IE属性页),选择隐藏选项卡,把设置调到最高,确定.
<br />
4.重新开IE,登录你刚才登录过的站点,怎么登都等不上去的.
<br />
<br />
2.Session和Cookie的关系
<br />
当前维持会话状态的途径有且只有两种种
<br />
第一种:Cookie,最常见的,95%以上的会话都是Cookie的功劳.
<br />
第二种:URL重写,把SessionID附加到URL中,JSP实现了但用的不多.
<br />
如果你用过session,你可能很奇怪:我们一般都是用session维持会话,这里怎么没有?
<br />
答案很简单:上面两种都是途径,Session是我们的目的.一句话概括Session和Cookie的关系:Cookie是维持Session最常见的一种途径.
<br />
<br />
3.Cookie的过期和Session的超时
<br />
你可以自己设置Cookie的过期(其实是服务器替你设置的),如果你设置为用不过期,
<br />
以后就都不用再重新登陆了,如果这台机器就你一个人用完全可以这样设置,否则
<br />
最好不要这样设置.如果你很长时间没有反应,就是没有新的请求,Session就有可能
<br />
过期,你可能遇到这样的情况:明明已经登录了,过了一会儿回来却说我没有登录
<br />
提示重新登录.就是因为Session过期了,服务器可以设置过期的时间.
<br />
<br />
4.禁用了Cookie如何实现会话
<br />
如果客户端完全禁用Cookie,将会发生什么现象:
<br />
对于ASP,无法跟踪会话,也就是每个请求都当作新的请求.
<br />
对于JSP,可以通过重写URL实现会话,session.encodeURL(String path)
<br />
session.encodeURL("index.jsp")=index.jsp;jsessionid=431D980051204FC8DC3
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BF75840F7AF71
<br />
可以看到后面的sessionid并没有包括在QueryString中(在?后面)
<br />
对于ASP.NET 同样支持重写URL,学习JSP的,不过JSP并不是所有的WebServer都支持重写URL
<br />
5.QueryString和HiddenForm
<br />
你可能觉得他们也可以维持会话，但是事实上是不可以的，他们只能传递参数。不过在ASP.NET中的服务器事件模型广泛了使用了Hidden来表示控件的viewState(这个也是ASP.NET比ASP,JSP先进的地方,是一种全新的技术)
<br />
为什么他们只能传递参数而不能实现会话呢?大致过程是这样的:
<br />
服务器接收到一个请求,如果没有获得SessionID,就产生一个新的会话.可能你认为这样可以保持会话 url?sessionid=234234234234.
<br />
这是一个误区,因为服务器已经处在一个新的会话中了,只不过可以获得上次会话的ID号而已.
<br />
<br />
6.QueryString和HiddenForm的区别
<br />
QueryString是URL中问号后面的?querystring.一般浏览器都把URL限制在255个字符以内所以没办法传递大量的数据,方法必须为get.HiddenForm是表单数据,方法为可以是get或者post(一般用post)
<br />
<br />
7.误区
<br />
我看到有人在论坛上说在自己的Web服务器上构建一个Session,然后链接到别人的程序这样可以越过验证.Session只在同一个
Application中才有效,所以这个设想是徒劳的,不过如果你们的程序是同一个Application中的(比如一些个人主页空间就有可能)是可以
这样做的.
<br />
<br />
8.题外话
<br />
利用Cookie攻击,因为客户端完全禁用Cookie之后,每次请求服务器都要产生一个会话.如果会话超时时间是15分钟的话,我们通过完全禁用Cookie的方法在15分钟内不停的请求让服务器产生大量的会话,实行DOS攻击(前提是大量的请求和服务器不做过滤)
<img src ="http://www.blogjava.net/conans/aggbug/299650.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-10-25 10:59 <a href="http://www.blogjava.net/conans/articles/299650.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 各大型网站架构分析收集</title><link>http://www.blogjava.net/conans/articles/293370.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Mon, 31 Aug 2009 12:57:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/293370.html</guid><description><![CDATA[1. PlentyOfFish 网站架构学习<br />
<a href="http://www.dbanotes.net/arch/plentyoffish_arch.html" target="_blank">http://www.dbanotes.net/arch/plentyoffish_arch.html</a><br />
<br />
采取 Windows 技术路线的 Web 2.0 站点并不多，除了 MySpace ，另外就是这个
PlentyOfFish。这个站点提供 &#8220;Online Dating&#8221;
服务。一个令人津津乐道的、惊人的数据是这个只有一个人(创建人Markus Frind）的站点价值 10 亿，估计要让很多人眼热，更何况
Markus Frind 每天只用两个小时打理网站&#8211;可操作性很强嘛。<br />
<br />
2. 从LiveJournal后台发展看 大型网站系统架构以及性能优化方法<br />
<a href="http://www.example.net.cn/archives/2006/03/olivejournaloio.html" target="_blank">http://www.example.net.cn/archives/2006/03/olivejournaloio.html</a><br />
<br />
LiveJournal是99年始于校园中的项目，几个人出于爱好做了这样一个应用，以实现以下功能：<br />
* 博客，论坛<br />
* 社会性网络，找到朋友<br />
* 聚合，把朋友的文章聚合在一起<br />
<br />
LiveJournal采用了大量的开源软件，甚至它本身也是一个开源软件。<br />
<br />
在上线后，LiveJournal实现了非常快速的增长：<br />
* 2004年4月份：280万注册用户。<br />
* 2005年4月份：680万注册用户。<br />
* 2005年8月份：790万注册用户。<br />
* 达到了每秒钟上千次的页面请求及处理。<br />
* 使用了大量MySQL服务器。<br />
* 使用了大量通用组件。<br />
<br />
3. YouTube 的架构扩展<br />
<a href="http://www.dbanotes.net/opensource/youtube_web_arch.html" target="_blank">http://www.dbanotes.net/opensource/youtube_web_arch.html</a><br />
<br />
在西雅图扩展性的技术研讨会上，YouTube 的 Cuong Do 做了关于 YouTube Scalability
的报告。视频内容在 Google Video 上有(地址)，可惜国内用户看不到。<br />
Kyle Cordes 对这个视频中的内容做了介绍。里面有不少技术性的内容。值得分享一下。(Kyle Cordes
的介绍是本文的主要来源)<br />
<br />
4. WikiPedia 技术架构学习分享<br />
<a href="http://www.dbanotes.net/opensource/wikipedia_arch.html" target="_blank">http://www.dbanotes.net/opensource/wikipedia_arch.html</a><br />
<br />
维基百科(WikiPedia.org)位列世界十大网站，目前排名第八位。这是开放的力量。<br />
<br />
来点直接的数据：<br />
<br />
* 峰值每秒钟3万个 HTTP 请求<br />
* 每秒钟 3Gbit 流量, 近乎375MB<br />
* 350 台 PC 服务器<br />
<br />
5. Tailrank 网站架构<br />
<a href="http://www.dbanotes.net/review/tailrank_arch.html" target="_blank">http://www.dbanotes.net/review/tailrank_arch.html</a><br />
<br />
每天数以千万计的 Blog 内容中，实时的热点是什么? Tailrank 这个 Web 2.0 Startup
致力于回答这个问题。<br />
<br />
专门爆料网站架构的 Todd Hoff 对 Kevin Burton 进行了采访。于是我们能了解一下 Tailrank
架构的一些信息。每小时索引 2400 万的 Blog 与 Feed，内容处理能力为 160-200Mbps，IO
写入大约在10-15MBps。每个月要处理 52T 之多的原始数据。Tailrank
所用的爬虫现在已经成为一个独立产品：spinn3r。<br />
<br />
6. LinkedIn 架构笔记<br />
<a href="http://www.dbanotes.net/arch/linkedin.html" target="_blank">http://www.dbanotes.net/arch/linkedin.html</a><br />
<br />
LinkedIn 雇员有 180 个，在 Web 2.0 公司中算是比较多的，不过人家自从 2006 年就盈利了，这在 Web 2.0
站点中可算少的。用户超过 1600 万，现在每月新增 100 万，50％ 会员来自海外(中国用户不少，也包括我).<br />
<br />
7. Yahoo！社区架构<br />
<a href="http://www.dbanotes.net/arch/yahoo_arch.html" target="_blank">http://www.dbanotes.net/arch/yahoo_arch.html</a><br />
<br />
旧金山举行的 QCon
会议带给我们很多新鲜的信息。虽然没机会参加，但是看看各个网站&#8221;晒架构&#8221;也是个比较过瘾的事情。请参观并收藏这个页面：Architectures
you&#8217;ve always wondered about。<br />
<br />
8. Craigslist 的数据库架构<br />
<a href="http://www.dbanotes.net/database/craigslist_database_arch.html" target="_blank">http://www.dbanotes.net/database/craigslist_database_arch.html</a><br />
<br />
Craigslist 绝对是互联网的一个传奇公司。根据以前的一则报道：<br />
<br />
每月超过 1000 万人使用该站服务，月浏览量超过 30 亿次，(Craigslist每月新增的帖子近 10
亿条??)网站的网页数量在以每年近百倍的速度增长。Craigslist 至今却只有 18 名员工(现在可能会多一些了)。<br />
<br />
9. Fotolog.com 的技术信息拾零<br />
<a href="http://www.dbanotes.net/review/fotolog_arch.html" target="_blank">http://www.dbanotes.net/review/fotolog_arch.html</a><br />
<br />
尽管是世界上最大的图片服务网站, Fotolog.com 在国内的名气并不是很响亮, 每当提到图片服务, 很多人第一个会想起
Flickr. 但实际上 Fotolog 也的确是很猛的, Alexa 上的排名一直在 Flickr 前面, 目前注册用户超过
1100 万. 而前不久也卖了一个好价钱, 9000 万美金. 算下来的话, 1 个注册用户大约 9 美金. Yupoo
的刘平阳可以偷着算算自己的网站如果卖给老外是怎样一个价格了.<br />
<br />
10. Digg 网站架构<br />
<a href="http://www.dbanotes.net/arch/digg_arch_cache_and_shard.html" target="_blank">http://www.dbanotes.net/arch/digg_arch_cache_and_shard.html</a><br />
<br />
Digg 工程师采用 LAMP (Linux, Apache, MySQL and PHP) 模式。这个 Alexa 排名在 100
左右的、自我估价 1.5 亿美金的站点目前有超过 100 台的 PC 服务器(足够少了)，可以粗略分成三个部分：数据库服务器，Web
服务器，搜索服务器。<br />
<br />
11. Amazon 的 Dynamo 架构<br />
<a href="http://www.dbanotes.net/techmemo/amazon_dynamo.html" target="_blank">http://www.dbanotes.net/techmemo/amazon_dynamo.html</a><br />
<br />
我在 DBAnotes.net 上记录过不少比较大的网站架构分析(eg: eBay [1], eBay [2]) ，Amazon
一直找不到太多的资料。国庆期间读到了一篇关于 Amazon Dynamo 的论文，非常精彩。Amazon Dynamo
这个高可用、可扩展存储体系支撑了Amazon 不少核心服务.<br />
<br />
12. 财帮子（caibangzi.com）网站架构<br />
<a href="http://www.dbanotes.net/arch/caibangzi_web_arch.html" target="_blank">http://www.dbanotes.net/arch/caibangzi_web_arch.html</a><br />
<br />
财帮子(caibangzi.com) 定位在&#8221;基金理财社区&#8221;。是国内访问量最大的基于 Ruby on rails 的 startup
项目。&#8220;理财&#8221;这个词据说是光大银行发明的，且不去管，不可否认的是，目前国内&#8221;理财&#8221;是个很有潜力的切入点。财帮子网站潜在用户群还是很大的。<br />
<br />
13. 了解一下 Technorati 的后台数据库架构<br />
<a href="http://www.dbanotes.net/web/technorati_db_arch.html" target="_blank">http://www.dbanotes.net/web/technorati_db_arch.html</a><br />
<br />
目前处理着大约 10Tb 核心数据, 分布在大约 20 台机器上.通过复制, 多增加了 100Tb 数据, 分布在 200 台机器上.
每天增长的数据 1TB. 通过 SOA 的运用, 物理与逻辑的访问相隔离,　似乎消除了数据库的瓶颈. 值得一提的是,
该扩展过程始终是利用普通的硬件与开源软件来完成的. 毕竟 , Web 2.0 站点都不是烧钱的主.
从数据量来看，这绝对是一个相对比较大的 Web 2.0 应用.<br />
<br />
14. 说说大型高并发高负载网站的系统架构<br />
<a href="http://www.toplee.com/blog/?p=71" target="_blank">http://www.toplee.com/blog/?p=71</a><br />
<br />
我在CERNET做过拨号接入平台的搭建，而后在Yahoo&amp;3721从事过搜索引擎前端开发，又在MOP处理过大型社区猫扑大杂烩的架构升级等
工作，同时自己接触和开发过不少大中型网站的模块，因此在大型网站应对高负载和并发的解决方案上有一些积累和经验，可以和大家一起探讨一下。<br />
<br />
15. 大型高负载网站架构 的感想<br />
<a href="http://atman.memoab.com/articles/194" target="_blank">http://atman.memoab.com/articles/194</a><br />
<br />
转自：http://blog.csdn.net/lovingprince/archive/2008/11/26/3379710.aspx<br />
<img src ="http://www.blogjava.net/conans/aggbug/293370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-08-31 20:57 <a href="http://www.blogjava.net/conans/articles/293370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Memcached在大型网站中应用</title><link>http://www.blogjava.net/conans/articles/292623.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 26 Aug 2009 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/292623.html</guid><description><![CDATA[memcached是一个高性能的分布式的内存对象缓存系统，通过在内存里维护一个统一的巨大的hash表，它能够用来存储各种格式的数据，包括图像、视
频、文件以及数据库检索的结果等。最初为了加速 LiveJournal
访问速度而开发的,后来被很多大型的网站采用。起初作者编写它可能是为了提高动态网页应用，为了减轻数据库检索的压力，来做的这个缓存系统。它的缓存是一
种分布式的，也就是可以允许不同主机上的多个用户同时访问这个缓存系统， 这种方法不仅解决了共享内存只能是单机的弊端，
同时也解决了数据库检索的压力，最大的优点是提高了访问获取数据的速度！基于memcached作者对分布式cache的理解和解决方案。
memcached完全可以用到其他地方 比如分布式数据库， 分布式计算等领域。 <br />
1、 memcached 协议理解
<br />
memcache是为了加快http://www.livejournal.com/访问速度而诞生的一个项目。
<br />
它的官方主页是：http://www.danga.com/memcached/
<br />
目前在网站开发中应用较少，主要的应用有：
<br />
http://www.danga.com/memcached/users.bml
<br />
在国内的网站开发中，还很少没见到有应用的，中文资料十分匮乏。
<br />
工作机制：通过在内存中开辟一块区域来维持一个大的hash表来加快页面访问速度，和数据库是独立的。但是目前主要用来缓存数据库的数据。允许多
个server通过网络形成一个大的hash，用户不必关心数据存放在哪，只调用相关接口就可。存放在内存的数据通过LRU算法进行淘汰出内存。同时可以
通过删除和设置失效时间来淘汰存放在内存的数据。
<br />
2、 memcached 使用入门
<br />
2.1 memcached的安装
<br />
&nbsp; ?&lt;1&gt;memcached服务的安装
<br />
&nbsp; 先检查linux内核版本，建议将memcached 安装在2.6以上。
<br />
&nbsp; 因为memcached 需要用到libevent和 epoll 。
<br />
memcached安装前首先确定你的服务器上面安装了libevent库，
<br />
libevent下载地址（ http://www.monkey.org/~provos/libevent/）。
<br />
下载memcached的源码（ http://www.danga.com/memcached/download.bml）。
<br />
Memcached最初是用perl写的，现在的版本是用c写的。
<br />
下载后拷贝到一个目录，安装需要root用户来执行
<br />
tar -zxvf memcached-1.1.12.tar.gz
<br />
cd memcached-1.1.12
<br />
./configure
<br />
这里必须先要configure, 它会检测你的系统情况，然后生成一个config.h文件和其它的几个文件，另外和其它的configure一样，你可以配置它的安装路径等等。默认应用程序安装在/usr/local/bin目录下。
<br />
make //编译
<br />
make install //安装
<br />
&lt;2&gt;memcached客户端的安装
<br />
根据memcached协议，用户可以自己写出符合自己要求的客户端程序。目前http://www.danga.com/memcached/download.bml
<br />
提供perl,c,java,python,php等客户端程序供下载和参考。下面我就以perl客户端程序为例说明客户端的安装：
<br />
下载后拷贝到一个目录，安装需要root用户来执行
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=tar%20-zxvf%20Cache-Memcached-1.14.tar.gz%0Acd%20Cache-Memcached-1.14%0Aperl%20makefile.pl%0Amake%0Amake%20install%0Amake%20test" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>tar&nbsp;-zxvf&nbsp;Cache-Memcached-</span><span class="number">1.14</span><span>.tar.gz&nbsp;&nbsp;</span></span></li>
    <li><span>cd&nbsp;Cache-Memcached-<span class="number">1.14</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>perl&nbsp;makefile.pl&nbsp;&nbsp;</span></li>
    <li><span>make&nbsp;&nbsp;</span></li>
    <li><span>make&nbsp;install&nbsp;&nbsp;</span></li>
    <li><span>make&nbsp;test&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">tar -zxvf Cache-Memcached-1.14.tar.gz
cd Cache-Memcached-1.14
perl makefile.pl
make
make install
make test</pre>
这样就安装好了memcahced， 启动memcached就可使用分布式缓存系统了！
<br />
2.2 快速入门
<br />
&lt;1&gt; memcached服务的启动
<br />
memcached的启动非常简单，它没有配置文件，只要配置好几个参数就可以使用了。下面我以一个实际应用的例子，具体说明一下：
<br />
memcached ?d ?m 500&nbsp; -l 64.128.191.151 -p 11211 -vv &gt;&gt;/var/www/kelly/test/logs/memcached_$$.log
<br />
启动的这个memcached为一个后台守护进程模式（-d), 然后缓存的空间为500M（-m),
监听(-l)服务器64.128.191.15的11211号端口(-p).,将日志写道/var/www/kelly/test/logs
/memcached_$$.log(-vv)。
<br />
其实memcached的参数也非常的有限,就下面这几个：
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3F%20%20-p%20port%20number%20to%20listen%20on%20%0A%3F%20%20-l%20interface%20to%20listen%20on%2C%20default%20is%20INDRR_ANY%20%0A%3F%20%20-d%20run%20as%20a%20daemon%20%0A%3F%20%20-r%20maximize%20core%20file%20limit%20%0A%3F%20%20-u%20assume%20identity%20of%20(only%20when%20run%20as%20root)%20%0A%3F%20%20-m%20max%20memory%20to%20use%20for%20items%20in%20megabytes%2C%20default%20is%2064%20MB%20%0A%3F%20%20-M%20return%20error%20on%20memory%20exhausted%20(rather%20than%20removing%20items)%20%0A%3F%20%20-c%20max%20simultaneous%20connections%2C%20default%20is%201024%20%0A%20%20%20%20%20%20%20%20%20%20%3F%20%20-k%20lock%20down%20all%20paged%20memory%20%0A%3F%20%20-v%20verbose%20(print%20errors%2Fwarnings%20while%20in%20event%20loop)%20%0A%3F%20%20-vv%20very%20verbose%20(also%20print%20client%20commands%2Freponses)%20%0A%3F%20%20-h%20print%20this%20help%20and%20exit%20%0A%3F%20%20-i%20print%20memcached%20and%20libevent%20license%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>?&nbsp;&nbsp;-p&nbsp;port&nbsp;number&nbsp;to&nbsp;listen&nbsp;on&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>?&nbsp;&nbsp;-l&nbsp;<span class="keyword">interface</span><span>&nbsp;to&nbsp;listen&nbsp;on,&nbsp;</span><span class="keyword">default</span><span>&nbsp;is&nbsp;INDRR_ANY&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>?&nbsp;&nbsp;-d&nbsp;run&nbsp;as&nbsp;a&nbsp;daemon&nbsp;&nbsp;&nbsp;</span></li>
    <li><span>?&nbsp;&nbsp;-r&nbsp;maximize&nbsp;core&nbsp;file&nbsp;limit&nbsp;&nbsp;&nbsp;</span></li>
    <li><span>?&nbsp;&nbsp;-u&nbsp;assume&nbsp;identity&nbsp;of&nbsp;(only&nbsp;when&nbsp;run&nbsp;as&nbsp;root)&nbsp;&nbsp;&nbsp;</span></li>
    <li><span>?&nbsp;&nbsp;-m&nbsp;max&nbsp;memory&nbsp;to&nbsp;use&nbsp;<span class="keyword">for</span><span>&nbsp;items&nbsp;in&nbsp;megabytes,&nbsp;</span><span class="keyword">default</span><span>&nbsp;is&nbsp;</span><span class="number">64</span><span>&nbsp;MB&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>?&nbsp;&nbsp;-M&nbsp;<span class="keyword">return</span><span>&nbsp;error&nbsp;on&nbsp;memory&nbsp;exhausted&nbsp;(rather&nbsp;than&nbsp;removing&nbsp;items)&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>?&nbsp;&nbsp;-c&nbsp;max&nbsp;simultaneous&nbsp;connections,&nbsp;<span class="keyword">default</span><span>&nbsp;is&nbsp;</span><span class="number">1024</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;&nbsp;-k&nbsp;lock&nbsp;down&nbsp;all&nbsp;paged&nbsp;memory&nbsp;&nbsp;&nbsp;</span></li>
    <li><span>?&nbsp;&nbsp;-v&nbsp;verbose&nbsp;(print&nbsp;errors/warnings&nbsp;<span class="keyword">while</span><span>&nbsp;in&nbsp;event&nbsp;loop)&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>?&nbsp;&nbsp;-vv&nbsp;very&nbsp;verbose&nbsp;(also&nbsp;print&nbsp;client&nbsp;commands/reponses)&nbsp;&nbsp;&nbsp;</span></li>
    <li><span>?&nbsp;&nbsp;-h&nbsp;print&nbsp;<span class="keyword">this</span><span>&nbsp;help&nbsp;and&nbsp;exit&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>?&nbsp;&nbsp;-i&nbsp;print&nbsp;memcached&nbsp;and&nbsp;libevent&nbsp;license&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">?  -p port number to listen on
?  -l interface to listen on, default is INDRR_ANY
?  -d run as a daemon
?  -r maximize core file limit
?  -u assume identity of (only when run as root)
?  -m max memory to use for items in megabytes, default is 64 MB
?  -M return error on memory exhausted (rather than removing items)
?  -c max simultaneous connections, default is 1024
?  -k lock down all paged memory
?  -v verbose (print errors/warnings while in event loop)
?  -vv very verbose (also print client commands/reponses)
?  -h print this help and exit
?  -i print memcached and libevent license </pre>
<br />
我们也可以将这个启动脚本写道/etc/rc.d或者/erc/rc.local，这样可以在服务器启动时候执行。
<br />
&lt;2&gt; memcached客户端的连接
<br />
下面我就以perl客户端程序为例说明客户端的连接:
<br />
启动两个memcached server
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=memcached%20%3Fd%20%3Fm%20500%20%20-l%2064.128.191.151%20-p%2011211%20-vv%20%3E%3E%2Fvar%2Fwww%2Fkelly%2Ftest%2Flogs%2Fmemcached_%24%24.log%0Amemcached%20%3Fd%20%3Fm%20500%20%20-l%2064.128.191.151%20-p%2011212%20-vv%20%3E%3E%2Fvar%2Fwww%2Fkelly%2Ftest%2Flogs%2Fmemcached_%24%24.log" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>memcached&nbsp;?d&nbsp;?m&nbsp;</span><span class="number">500</span><span>&nbsp;&nbsp;-l&nbsp;</span><span class="number">64.128</span><span>.</span><span class="number">191.151</span><span>&nbsp;-p&nbsp;</span><span class="number">11211</span><span>&nbsp;-vv&nbsp;&gt;&gt;/var/www/kelly/test/logs/memcached_$$.log&nbsp;&nbsp;</span></span></li>
    <li><span>memcached&nbsp;?d&nbsp;?m&nbsp;<span class="number">500</span><span>&nbsp;&nbsp;-l&nbsp;</span><span class="number">64.128</span><span>.</span><span class="number">191.151</span><span>&nbsp;-p&nbsp;</span><span class="number">11212</span><span>&nbsp;-vv&nbsp;&gt;&gt;/var/www/kelly/test/logs/memcached_$$.log&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">memcached ?d ?m 500  -l 64.128.191.151 -p 11211 -vv &gt;&gt;/var/www/kelly/test/logs/memcached_$$.log
memcached ?d ?m 500  -l 64.128.191.151 -p 11212 -vv &gt;&gt;/var/www/kelly/test/logs/memcached_$$.log</pre>
<br />
perl客户端程序
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%23!%2Fusr%2Fbin%2Fperl%0Ause%20Cache%3A%3AMemcached%3B%0Amy%20%24memd%20%3D%20new%20Cache%3A%3AMemcached%20%7B%0A%20%20%20%20'servers'%20%3D%3E%20%5B%20%2264.128.191.15%3A11211%22%20%2C%20%2264.128.191.15%3A11212%22%5D%2C%0A%20%20%7D%3B%0Amy%20%24val%20%3D%20%24memd-%3Eget(%20%22my_key%22%20)%3B%0Aif%20(%20%24val%20)%0A%7B%0A%20%20%20print%20%22Value%20is%20'%24val'%5Cn%22%3B%0A%7D%0A%23%20Set%20a%20value%0A%24memd-%3Eset(%22my_key%22%2C%20%22123%22)%3B%0A%24memd-%3Edisconnect_all()%3B" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>#!/usr/bin/perl&nbsp;&nbsp;</span></span></li>
    <li><span>use&nbsp;Cache::Memcached;&nbsp;&nbsp;</span></li>
    <li><span>my&nbsp;$memd&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;Cache::Memcached&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">'servers'</span><span>&nbsp;=&gt;&nbsp;[&nbsp;</span><span class="string">"64.128.191.15:11211"</span><span>&nbsp;,&nbsp;</span><span class="string">"64.128.191.15:11212"</span><span>],&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;};&nbsp;&nbsp;</span></li>
    <li><span>my&nbsp;$val&nbsp;=&nbsp;$memd-&gt;get(&nbsp;<span class="string">"my_key"</span><span>&nbsp;);&nbsp;&nbsp;</span></span></li>
    <li><span><span class="keyword">if</span><span>&nbsp;(&nbsp;$val&nbsp;)&nbsp;&nbsp;</span></span></li>
    <li><span>{&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;print&nbsp;<span class="string">"Value&nbsp;is&nbsp;'$val'\n"</span><span>;&nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
    <li><span>#&nbsp;Set&nbsp;a&nbsp;value&nbsp;&nbsp;</span></li>
    <li><span>$memd-&gt;set(<span class="string">"my_key"</span><span>,&nbsp;</span><span class="string">"123"</span><span>);&nbsp;&nbsp;</span></span></li>
    <li><span>$memd-&gt;disconnect_all();&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">#!/usr/bin/perl
use Cache::Memcached;
my $memd = new Cache::Memcached {
'servers' =&gt; [ "64.128.191.15:11211" , "64.128.191.15:11212"],
};
my $val = $memd-&gt;get( "my_key" );
if ( $val )
{
print "Value is '$val'\n";
}
# Set a value
$memd-&gt;set("my_key", "123");
$memd-&gt;disconnect_all();</pre>
?运行测试
<br />
$ perl test-memcache.pl
<br />
$ perl test-memcache.pl
<br />
Value is '123'
<br />
可以看到，第一次没有取得my_key，第二次从memcached中得到my_key的值。
<br />
同时通过查看日志，可以发现的确存储在两个memcache&nbsp; server中。
<br />
这个简单的例子，解释了如何在memcached中存取数据，以及memcache是真正的分布式缓存系统。
<br />
当然，这还只是很简单的例子，体现不出memcache的优势，下面将通过一个很具体的例子，给出详细的应用。
<br />
3、 memcached在Zorpia的应用
<br />
http://www.zorpia.com 是一个网页相册，博客，交友，论坛的大型网站公司。现在已有超过140万活跃使用者遍布美国，香港，东南亚，欧洲，澳洲，亚洲等其它地区。每天的访问量都在增长，已成为全世界排名第五的社会生活关系网。
<br />
Memcached也采用了memcached来提高网站的访问速度，并且取得了很好的效果，我在负责zorpia的memcached项目时候积累了一些经验，主要的做法如下：
<br />
1） 通过对memcache的perl客户端进行包装，定制自己的客户端。
<br />
2） 通过制定符合zorpia规范的hash key命名规范
<br />
?&nbsp; ? memcache中需要存储的内容的key均由string组成。
<br />
这个string统一由一个memcache.pm的subroutine来实现。(假设这个subroutine是 get_key() )
<br />
?&nbsp; ? memcache中存放两种形式的数据
<br />
&nbsp; (1) result of SQL query :
<br />
&nbsp; (2) 普通变量(variable)
<br />
&nbsp; 这两种数据的key的组合方式是不相同的，由get_key进行判断和完成
<br />
?&nbsp; ? 关于get_key 和 naming rule
<br />
&nbsp; get_key subroutine完成所有memcache key的命名，naming rule也是在它里边体现：
<br />
&nbsp; (1)输入参数 －－ hash结构，里边定义了当前需要存放的数据的信息
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结构
<br />
&nbsp; (2)返回值 －－ string，返回数据的key_name
<br />
?必须确定 get_key 的传入hash的结构，
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hash中主要有两个元素
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type --- 定义当前数据结构的类型 ，有 'var' , 'sql'两种值
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object --- 存放当前数据结构的详细信息，
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当 type eq 'var'时，object表示变量的名字，该名字由程序员指定
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当 type eq 'sql'时，object包含所存放sql的主要基本信息，hash结构，也由程序员按照规则制定
<br />
&nbsp;&nbsp;&nbsp;&nbsp; ## 当variable 数据类型，比较简单
<br />
&nbsp;&nbsp;&nbsp;&nbsp; $var_hash = {
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type =&gt; 'var',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ## var表示当前类型是 variable&nbsp;&nbsp;
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object =&gt; 'language',&nbsp; ##&nbsp; language代表variable的名字
<br />
&nbsp;&nbsp;&nbsp;&nbsp; };
<br />
生成的key是Zorpia::var| language
<br />
&nbsp;&nbsp;&nbsp;&nbsp; ## sql 数据
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 比如select first_name from user where user_id =2那么hash为
<br />
&nbsp;&nbsp;&nbsp;&nbsp; $sql_hash = {
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type =&gt; 'sql',
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object =&gt; {
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; table =&gt; {table2=&gt;"user",},&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ## sql 查询的表
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column =&gt; {column1=&gt;"first_name",},&nbsp; ## sql所要查询的column
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; condition =&gt; { user_id =&gt;"2",},&nbsp; ## sql条件
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },
<br />
&nbsp;&nbsp;&nbsp;&nbsp; };
<br />
生成的key是Zorpia::sql|user|first_name| user_id =2
<br />
&nbsp;&nbsp;&nbsp;&nbsp; get_key subroutine必须对传入hash进行判断，对不同类型的数据按照不同的方式组合，形成key，返回给使用者。这个key，必须保证其唯一性：
<br />
比如：所有字母小写，一些数组在组合成key之前必须首先排序
<br />
? ? get_key函数
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=sub%20get_key%7B%0Amy%20%24hash%20%3D%20shift%3B%0Areturn%20undef%20unless%20%24hash%20%26%26%20ref%20%24hash%20eq%20%22HASH%22%3B%0Amy%20%24type%20%3D%20%24hash-%3E%7Btype%7D%3B%0Amy%20%24key_name%3B%0Aif%20(%24type%20eq%20'sql')%20%7B%0Amy%20(%24table_key%2C%24column_key%2C%24condition_key)%3B%0A%24table_key%3D_get_key(%24hash-%3E%7Bobject%7D-%3E%7Btable%7D)%3B%0A%24column_key%3D_get_key(%24hash-%3E%7Bobject%7D-%3E%7Bcolumn%7D)%3B%0A%24condition_key%3D_get_key(%24hash-%3E%7Bobject%7D-%3E%7Bcondition%7D)%3B%0A%24key_name%20%3D%20join('%7C'%2C%24type%2C%24table_key%2C%24column_key%2C%24condition_key)%3B%0A%23Currently%20the%20length%20limit%20of%20a%20key%20is%20set%20at%20250%20characters%0Aif%20(length(%24key_name)%3E250)%0A%7B%0A%24key_name%3Dsubstr(0%2C250%2C%24key_name)%3B%20%0A%7D%0A%7D%0Aelsif(%24type%20eq%20'var')%0A%7B%0A%24key_name%20%3D%20join('%7C'%2C%24type%2C%24hash-%3E%7Bobject%7D)%3B%0A%7D%0Areturn%20%24key_name%3B%0A%7D%0Asub%20_get_key%0A%7B%0Amy%20%24hash%3Dshift%3B%0Areturn%20undef%20unless%20%24hash%20%26%26%20ref%20%24hash%20eq%20%22HASH%22%3B%0Amy%20(%24t%2C%24ret%2C%24i)%3B%0Aforeach%20%24i%20(sort%20keys%20%25%24hash)%0A%7B%0A%20%20%24i%3D~s%2F%5E%5Cs%2B%7C%5Cs%2B%24%2F%2Fg%3B%0A%20%20%24hash-%3E%7B%24i%7D%3D~s%2F%5E%5Cs%2B%7C%5Cs%2B%24%2F%2Fg%3B%0A%20%20%20push(%40%24t%2Clc(%22%24i%3D%24hash-%3E%7B%24i%7D%22))%3B%0A%7D%0A%24ret%3Djoin('%3A'%2Csort%20%7B%20%24a%20cmp%20%24b%20%7D%20%40%24t)%3B%0Areturn%20%24ret%3B%20%20%20%20%0A%7D" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>sub&nbsp;get_key{&nbsp;&nbsp;</span></span></li>
    <li><span>my&nbsp;$hash&nbsp;=&nbsp;shift;&nbsp;&nbsp;</span></li>
    <li><span><span class="keyword">return</span><span>&nbsp;undef&nbsp;unless&nbsp;$hash&nbsp;&amp;&amp;&nbsp;ref&nbsp;$hash&nbsp;eq&nbsp;</span><span class="string">"HASH"</span><span>;&nbsp;&nbsp;</span></span></li>
    <li><span>my&nbsp;$type&nbsp;=&nbsp;$hash-&gt;{type};&nbsp;&nbsp;</span></li>
    <li><span>my&nbsp;$key_name;&nbsp;&nbsp;</span></li>
    <li><span><span class="keyword">if</span><span>&nbsp;($type&nbsp;eq&nbsp;</span><span class="string">'sql'</span><span>)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li><span>my&nbsp;($table_key,$column_key,$condition_key);&nbsp;&nbsp;</span></li>
    <li><span>$table_key=_get_key($hash-&gt;{object}-&gt;{table});&nbsp;&nbsp;</span></li>
    <li><span>$column_key=_get_key($hash-&gt;{object}-&gt;{column});&nbsp;&nbsp;</span></li>
    <li><span>$condition_key=_get_key($hash-&gt;{object}-&gt;{condition});&nbsp;&nbsp;</span></li>
    <li><span>$key_name&nbsp;=&nbsp;join(<span class="string">'|'</span><span>,$type,$table_key,$column_key,$condition_key);&nbsp;&nbsp;</span></span></li>
    <li><span>#Currently&nbsp;the&nbsp;length&nbsp;limit&nbsp;of&nbsp;a&nbsp;key&nbsp;is&nbsp;set&nbsp;at&nbsp;<span class="number">250</span><span>&nbsp;characters&nbsp;&nbsp;</span></span></li>
    <li><span><span class="keyword">if</span><span>&nbsp;(length($key_name)&gt;</span><span class="number">250</span><span>)&nbsp;&nbsp;</span></span></li>
    <li><span>{&nbsp;&nbsp;</span></li>
    <li><span>$key_name=substr(<span class="number">0</span><span>,</span><span class="number">250</span><span>,$key_name);&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
    <li><span>elsif($type&nbsp;eq&nbsp;<span class="string">'var'</span><span>)&nbsp;&nbsp;</span></span></li>
    <li><span>{&nbsp;&nbsp;</span></li>
    <li><span>$key_name&nbsp;=&nbsp;join(<span class="string">'|'</span><span>,$type,$hash-&gt;{object});&nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
    <li><span><span class="keyword">return</span><span>&nbsp;$key_name;&nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
    <li><span>sub&nbsp;_get_key&nbsp;&nbsp;</span></li>
    <li><span>{&nbsp;&nbsp;</span></li>
    <li><span>my&nbsp;$hash=shift;&nbsp;&nbsp;</span></li>
    <li><span><span class="keyword">return</span><span>&nbsp;undef&nbsp;unless&nbsp;$hash&nbsp;&amp;&amp;&nbsp;ref&nbsp;$hash&nbsp;eq&nbsp;</span><span class="string">"HASH"</span><span>;&nbsp;&nbsp;</span></span></li>
    <li><span>my&nbsp;($t,$ret,$i);&nbsp;&nbsp;</span></li>
    <li><span>foreach&nbsp;$i&nbsp;(sort&nbsp;keys&nbsp;%$hash)&nbsp;&nbsp;</span></li>
    <li><span>{&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;$i=~s/^\s+|\s+$<span class="comment">//g;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;$hash-&gt;{$i}=~s/^\s+|\s+$<span class="comment">//g;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;push(<span class="annotation">@$t</span><span>,lc(</span><span class="string">"$i=$hash-&gt;{$i}"</span><span>));&nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
    <li><span>$ret=join(<span class="string">':'</span><span>,sort&nbsp;{&nbsp;$a&nbsp;cmp&nbsp;$b&nbsp;}&nbsp;</span><span class="annotation">@$t</span><span>);&nbsp;&nbsp;</span></span></li>
    <li><span><span class="keyword">return</span><span>&nbsp;$ret;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">sub get_key{
my $hash = shift;
return undef unless $hash &amp;&amp; ref $hash eq "HASH";
my $type = $hash-&gt;{type};
my $key_name;
if ($type eq 'sql') {
my ($table_key,$column_key,$condition_key);
$table_key=_get_key($hash-&gt;{object}-&gt;{table});
$column_key=_get_key($hash-&gt;{object}-&gt;{column});
$condition_key=_get_key($hash-&gt;{object}-&gt;{condition});
$key_name = join('|',$type,$table_key,$column_key,$condition_key);
#Currently the length limit of a key is set at 250 characters
if (length($key_name)&gt;250)
{
$key_name=substr(0,250,$key_name);
}
}
elsif($type eq 'var')
{
$key_name = join('|',$type,$hash-&gt;{object});
}
return $key_name;
}
sub _get_key
{
my $hash=shift;
return undef unless $hash &amp;&amp; ref $hash eq "HASH";
my ($t,$ret,$i);
foreach $i (sort keys %$hash)
{
$i=~s/^\s+|\s+$//g;
$hash-&gt;{$i}=~s/^\s+|\s+$//g;
push(@$t,lc("$i=$hash-&gt;{$i}"));
}
$ret=join(':',sort { $a cmp $b } @$t);
return $ret;
}</pre>
3） 制定需要应用memcached的规则
<br />
?经常访问的表user,user_details
<br />
?合理设定变量在memcached的生存周期
<br />
?将活跃用户的信息预先导入到memcached
<br />
?分别在多台机器上启动多个memcached服务
<br />
?编写脚本监控memcached服务是否活动
<br />
4） User表的具体应用举例
<br />
? 在 select时候
<br />
先查询memcahce里有没有，有的话，返回；否则从数据库select,在memcache里设置，返回。
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=my%20%24sql_hash%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20type%20%3D%3E%20'sql'%2C%0A%20%20%20%20%20%20%20%20%20object%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20table%20%3D%3E%20%7Btable1%3D%3E%22user%22%2C%7D%2C%0A%20%20%20%20%20%20%20column%20%3D%3E%20%7Bcolumn1%3D%3E%22user_id%22%2C%7D%2C%0A%20%20%20%20%20%20%20condition%20%3D%3E%20%7Bemail%3D%3E%24user_id%2C%7D%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20my%20%24key%3DZorpia%3A%3AMemCache%3A%3Aget_key(%24sql_hash)%3B%20%20%0A%20%20%20%20%20%20%20%20my%20%24user_id_by_email%3DZorpia%3A%3AMemCache%3A%3Aget(%24key)%3B%0A%20%20%20%20%20%20%20if(!%24user_id_by_email)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20my%20%24sth%3B%0A%20%20%20%20%20%20%20%20my%20%24query%20%3D%22select%20user_id%20from%20user%20where%20email%3D%3F%22%3B%0A%20%20%20%20%20%20%20%20%24sth%20%3D%20%24dbh-%3Eprepare(%24query)%3B%0A%20%20%20%20%20%20%20%20%24sth-%3Eexecute(%24user_id)%3B%0A%20%20%20%20%20%20%20%20my%20%24user1%20%3D%20%24sth-%3Efetchrow_hashref()%3B%0A%20%20%20%20%20%20%20%20%24user_id_by_email%3D%24user1-%3E%7B'user_id'%7D%3B%0A%20%20%20%20%20%20%20%20Zorpia%3A%3AMemCache%3A%3Aset(%24key%2C%24user_id_by_email%2C1800)%3B%0A%20%20%20%20%20%20%20%20%7D" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>my&nbsp;$sql_hash&nbsp;=&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;=&gt;&nbsp;<span class="string">'sql'</span><span>,&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object&nbsp;=&gt;&nbsp;{&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table&nbsp;=&gt;&nbsp;{table1=&gt;<span class="string">"user"</span><span>,},&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;column&nbsp;=&gt;&nbsp;{column1=&gt;<span class="string">"user_id"</span><span>,},&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;condition&nbsp;=&gt;&nbsp;{email=&gt;$user_id,},&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my&nbsp;$key=Zorpia::MemCache::get_key($sql_hash);&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my&nbsp;$user_id_by_email=Zorpia::MemCache::get($key);&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(!$user_id_by_email)&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my&nbsp;$sth;&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my&nbsp;$query&nbsp;=<span class="string">"select&nbsp;user_id&nbsp;from&nbsp;user&nbsp;where&nbsp;email=?"</span><span>;&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sth&nbsp;=&nbsp;$dbh-&gt;prepare($query);&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sth-&gt;execute($user_id);&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my&nbsp;$user1&nbsp;=&nbsp;$sth-&gt;fetchrow_hashref();&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$user_id_by_email=$user1-&gt;{<span class="string">'user_id'</span><span>};&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Zorpia::MemCache::set($key,$user_id_by_email,<span class="number">1800</span><span>);&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">my $sql_hash = {
type =&gt; 'sql',
object =&gt; {
table =&gt; {table1=&gt;"user",},
column =&gt; {column1=&gt;"user_id",},
condition =&gt; {email=&gt;$user_id,},
},
};
my $key=Zorpia::MemCache::get_key($sql_hash);
my $user_id_by_email=Zorpia::MemCache::get($key);
if(!$user_id_by_email)
{
my $sth;
my $query ="select user_id from user where email=?";
$sth = $dbh-&gt;prepare($query);
$sth-&gt;execute($user_id);
my $user1 = $sth-&gt;fetchrow_hashref();
$user_id_by_email=$user1-&gt;{'user_id'};
Zorpia::MemCache::set($key,$user_id_by_email,1800);
}</pre>
?在 update,insert,delete时候
<br />
先在数据库update,insert,delete,在memcache里设置，返回。
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%26Zorpia%3A%3ADB%3A%3Adata_entry_no_return(%24dbh%2C%22user%22%2C%22COUNT(*)%22%2C%22%24account_information_insert_statement%20user_id%3D%24current_user_id%22%2C%20%22user_id%3D%24current_user_id%22)%3B%0A%20%23add%20by%20kelly%0A%20my%20%24sql_hash%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20type%20%3D%3E%20'sql'%2C%0A%20%20%20%20%20%20%20%20%20object%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20table%20%3D%3E%20%7Btable1%3D%3E%22user%22%2C%7D%2C%0A%20%20%20%20%20%20%20column%20%3D%3E%20%7Bcolumn1%3D%3E%22user_id%22%2C%7D%2C%0A%20%20%20%20%20%20%20condition%20%3D%3E%20%7Buser_id%3D%3E%24current_user_id%2C%7D%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%7D%3B%0A%20%20my%20%24key%3DZorpia%3A%3AMemCache%3A%3Aget_key(%24sql_hash)%3B%0A%20%20my%20%24query%20%3D%20%22SELECT%20*%2C%20user_id%20AS%20id%20%20FROM%20%20%20user%20%20WHERE%20user_id%3D%3F%22%3B%0A%20%20my%20%24sth_memc%20%3D%20%24dbh-%3Eprepare(%24query)%3B%0A%20%20%24sth_memc-%3Eexecute(%24current_user_id)%3B%0A%20%20my%20%24user_memc%20%3D%20%24sth_memc-%3Efetchrow_hashref()%3B%0A%20%20%26Zorpia%3A%3AMemCache%3A%3Aset(%24key%2C%24user_memc%2C21600)%3B" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>&amp;Zorpia::DB::data_entry_no_return($dbh,</span><span class="string">"user"</span><span>,</span><span class="string">"COUNT(*)"</span><span>,</span><span class="string">"$account_information_insert_statement&nbsp;user_id=$current_user_id"</span><span>,&nbsp;</span><span class="string">"user_id=$current_user_id"</span><span>);&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;#add&nbsp;by&nbsp;kelly&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;my&nbsp;$sql_hash&nbsp;=&nbsp;{&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;=&gt;&nbsp;<span class="string">'sql'</span><span>,&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object&nbsp;=&gt;&nbsp;{&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table&nbsp;=&gt;&nbsp;{table1=&gt;<span class="string">"user"</span><span>,},&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;column&nbsp;=&gt;&nbsp;{column1=&gt;<span class="string">"user_id"</span><span>,},&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;condition&nbsp;=&gt;&nbsp;{user_id=&gt;$current_user_id,},&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;my&nbsp;$key=Zorpia::MemCache::get_key($sql_hash);&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;my&nbsp;$query&nbsp;=&nbsp;<span class="string">"SELECT&nbsp;*,&nbsp;user_id&nbsp;AS&nbsp;id&nbsp;&nbsp;FROM&nbsp;&nbsp;&nbsp;user&nbsp;&nbsp;WHERE&nbsp;user_id=?"</span><span>;&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;my&nbsp;$sth_memc&nbsp;=&nbsp;$dbh-&gt;prepare($query);&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;$sth_memc-&gt;execute($current_user_id);&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;my&nbsp;$user_memc&nbsp;=&nbsp;$sth_memc-&gt;fetchrow_hashref();&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&amp;Zorpia::MemCache::set($key,$user_memc,<span class="number">21600</span><span>);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">&amp;Zorpia::DB::data_entry_no_return($dbh,"user","COUNT(*)","$account_information_insert_statement user_id=$current_user_id", "user_id=$current_user_id");
#add by kelly
my $sql_hash = {
type =&gt; 'sql',
object =&gt; {
table =&gt; {table1=&gt;"user",},
column =&gt; {column1=&gt;"user_id",},
condition =&gt; {user_id=&gt;$current_user_id,},
},
};
my $key=Zorpia::MemCache::get_key($sql_hash);
my $query = "SELECT *, user_id AS id  FROM   user  WHERE user_id=?";
my $sth_memc = $dbh-&gt;prepare($query);
$sth_memc-&gt;execute($current_user_id);
my $user_memc = $sth_memc-&gt;fetchrow_hashref();
&amp;Zorpia::MemCache::set($key,$user_memc,21600);</pre>
4、 memcached的应用展望
<br />
使用了memcached以后， 我发现以前做过的很多的项目都可以应用它提高效率，包括最近做的&#8220;大单追踪&#8221;，
&#8220;数码搜索&#8221;等等。当然既然memcahced是分布式的缓存系统，那么它就是建立了一个分布式的平台， 我们可以用它来进行分布式的记数，
因为对于一个键值key我们可以设置它的数值以及有效期在参数中，另外还可以重新设置这个键值的数值。 所以我总结了一下目前可以应用到的地方：
<br />
&lt;1&gt;.数据库检索结果的缓存，也就是说可以有机的和数据库结合起来应用，提高效率。
<br />
&nbsp;&nbsp;&nbsp; 这也是目前memcached用到的最多的地方，比如用于大型网站等。
<br />
可以这样来实现：
<br />
打开memcached服务器连接
<br />
编写sql语句， 同时算出它的一个hash key值
<br />
获取这个hash值的memcached保存数据(get)
<br />
如果获取的这个hash值的数据存在。返回
<br />
否则连接数据库查找
<br />
把这个查找结果保存在memcached中(set)，可以设置有效期
<br />
返回查找结果
<br />
&lt;2&gt;.分布式计算
<br />
&lt;3&gt;.分布式共享数据
<br />
总之，memcached的机制比较灵活，可以适用于一切需要分布式缓存数据的地方，随着memcached逐渐为人所知，必将在更多的分布式应用领域大放异彩。
<br />
<br />
http://nio.infor96.com/php-memcached/
<br />
<br />
一、memcached 简介
<br />
<br />
在很多场合，我们都会听到 memcached 这个名字，但很多同学只是听过，并没有用过或实际了解过，只知道它是一个很不错的东东。这里简单介绍一下，memcached 是高效、快速的分布式内存对象缓存系统，主要用于加速 WEB 动态应用程序。
<br />
<br />
二、memcached 安装
<br />
<br />
首先是下载 memcached 了，目前最新版本是 1.1.12，直接从官方网站即可下载到 memcached-1.1.12.tar.gz。除此之外，memcached 用到了 libevent，我下载的是 libevent-1.1a.tar.gz。
<br />
<br />
接下来是分别将 libevent-1.1a.tar.gz 和 memcached-1.1.12.tar.gz 解开包、编译、安装：
<br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%23%20tar%20-xzf%20libevent-1.1a.tar.gz%23%20cd%20libevent-1.1a%23%20.%2Fconfigure%20--prefix%3D%2Fusr%23%20make%23%20make%20install%23%20cd%20..%23%20tar%20-xzf%20memcached-1.1.12.tar.gz%23%20cd%20memcached-1.1.12%23%20.%2Fconfigure%20--prefix%3D%2Fusr%23%20make%23%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>#&nbsp;tar&nbsp;-xzf&nbsp;libevent-</span><span class="number">1</span><span>.1a.tar.gz#&nbsp;cd&nbsp;libevent-</span><span class="number">1</span><span>.1a#&nbsp;./configure&nbsp;--prefix=/usr#&nbsp;make#&nbsp;make&nbsp;install#&nbsp;cd&nbsp;..#&nbsp;tar&nbsp;-xzf&nbsp;memcached-</span><span class="number">1.1</span><span>.</span><span class="number">12</span><span>.tar.gz#&nbsp;cd&nbsp;memcached-</span><span class="number">1.1</span><span>.</span><span class="number">12</span><span>#&nbsp;./configure&nbsp;--prefix=/usr#&nbsp;make#&nbsp;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java"># tar -xzf libevent-1.1a.tar.gz# cd libevent-1.1a# ./configure --prefix=/usr# make# make install# cd ..# tar -xzf memcached-1.1.12.tar.gz# cd memcached-1.1.12# ./configure --prefix=/usr# make# </pre>
make install安装完成之后，memcached 应该在 /usr/bin/memcached。
<br />
<br />
三、运行 memcached 守护程序
<br />
<br />
运行 memcached 守护程序很简单，只需一个命令行即可，不需要修改任何配置文件（也没有配置文件给你修改&nbsp; ）：
<br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <embed src="http://leeyin.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%2Fusr%2Fbin%2Fmemcached%20-d%20-m%20128%20-l%20192.168.1.1%20-p%2011211%20-u%20httpd" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
</div>
<ol class="dp-j" start="1">
    <li><span><span>/usr/bin/memcached&nbsp;-d&nbsp;-m&nbsp;</span><span class="number">128</span><span>&nbsp;-l&nbsp;</span><span class="number">192.168</span><span>.</span><span class="number">1.1</span><span>&nbsp;-p&nbsp;</span><span class="number">11211</span><span>&nbsp;-u&nbsp;httpd&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">/usr/bin/memcached -d -m 128 -l 192.168.1.1 -p 11211 -u httpd</pre>
参数解释：
<br />
<br />
-d 以守护程序（daemon）方式运行 memcached；-m 设置 memcached 可以使用的内存大小，单位为 M；-l
设置监听的 IP 地址，如果是本机的话，通常可以不设置此参数；-p 设置监听的端口，默认为 11211，所以也可以不设置此参数；-u
指定用户，如果当前为 root 的话，需要使用此参数指定用户。当然，还有其它参数可以用，man memcached 一下就可以看到了。
<br />
<br />
四、memcached 的工作原理
<br />
<br />
首先 memcached
是以守护程序方式运行于一个或多个服务器中，随时接受客户端的连接操作，客户端可以由各种语言编写，目前已知的客户端 API 包括
Perl/PHP/Python/Ruby/Java/C#/C 等等。PHP 等客户端在与 memcached
服务建立连接之后，接下来的事情就是存取对象了，每个被存取的对象都有一个唯一的标识符 key，存取操作均通过这个 key 进行，保存到
memcached 中的对象实际上是放置内存中的，并不是保存在 cache 文件中的，这也是为什么 memcached
能够如此高效快速的原因。注意，这些对象并不是持久的，服务停止之后，里边的数据就会丢失。
<br />
<br />
三、PHP 如何作为 memcached 客户端
<br />
<br />
有两种方法可以使 PHP 作为 memcached 客户端，调用 memcached 的服务进行对象存取操作。
<br />
<br />
第一种，PHP 有一个叫做 memcache 的扩展，Linux 下编译时需要带上 ?enable-memcache[=DIR] 选项，Window 下则在 php.ini 中去掉 php_memcache.dll 前边的注释符，使其可用。
<br />
<br />
除此之外，还有一种方法，可以避开扩展、重新编译所带来的麻烦，那就是直接使用 php-memcached-client。
<br />
<br />
本文选用第二种方式，虽然效率会比扩展库稍差一些，但问题不大。
<br />
<br />
四、PHP memcached 应用示例
<br />
<br />
首先 下载 memcached-client.php，在下载了 memcached-client.php
之后，就可以通过这个文件中的类&#8220;memcached&#8221;对 memcached 服务进行操作了。其实代码调用非常简单，主要会用到的方法有
add()、get()、replace() 和 delete()，方法说明如下：
<br />
<br />
add ($key, $val, $exp = 0)
<br />
往 memcached 中写入对象，$key 是对象的唯一标识符，$val 是写入的对象数据，$exp 为过期时间，单位为秒，默认为不限时间；
<br />
<br />
get ($key)
<br />
从 memcached 中获取对象数据，通过对象的唯一标识符 $key 获取；
<br />
<br />
replace ($key, $value, $exp=0)
<br />
使用 $value 替换 memcached 中标识符为 $key 的对象内容，参数与 add() 方法一样，只有 $key 对象存在的情况下才会起作用；
<br />
<br />
delete ($key, $time = 0)
<br />
删除 memcached 中标识符为 $key 的对象，$time 为可选参数，表示删除之前需要等待多长时间。
<br />
<br />
下面是一段简单的测试代码，代码中对标识符为 &#8216;mykey&#8217; 的对象数据进行存取操作：
<br />
<br />
//&nbsp; 包含 memcached 类文件require_once(&#8216;memcached-client.php&#8217;);//&nbsp;
选项设置$options = array(&nbsp;&nbsp;&nbsp; &#8217;servers&#8217; =&gt; array(&#8216;192.168.1.1:11211&#8242;),
//memcached 服务的地址、端口，可用多个数组元素表示多个 memcached 服务&nbsp;&nbsp;&nbsp; &#8216;debug&#8217; =&gt; true,&nbsp;
//是否打开 debug&nbsp;&nbsp;&nbsp; &#8216;compress_threshold&#8217; =&gt; 10240,&nbsp; //超过多少字节的数据时进行压缩&nbsp;&nbsp;&nbsp;
&#8216;persistant&#8217; =&gt; false&nbsp; //是否使用持久连接&nbsp;&nbsp;&nbsp; );//&nbsp; 创建 memcached 对象实例$mc =
new memcached($options);//&nbsp; 设置此脚本使用的唯一标识符$key = &#8216;mykey&#8217;;//&nbsp; 往 memcached
中写入对象$mc-&gt;add($key, &#8217;some random strings&#8217;);$val =
$mc-&gt;get($key);echo &#8220;n&#8221;.str_pad(&#8216;$mc-&gt;add() &#8217;, 60,
&#8216;_&#8217;).&#8220;n&#8221;;var_dump($val);//&nbsp; 替换已写入的对象数据值$mc-&gt;replace($key,
array(&#8217;some&#8217;=&gt;&#8216;haha&#8217;, &#8216;array&#8217;=&gt;&#8216;xxx&#8217;));$val =
$mc-&gt;get($key);echo &#8220;n&#8221;.str_pad(&#8216;$mc-&gt;replace() &#8217;, 60,
&#8216;_&#8217;).&#8220;n&#8221;;var_dump($val);//&nbsp; 删除 memcached 中的对象$mc-&gt;delete($key);$val
= $mc-&gt;get($key);echo &#8220;n&#8221;.str_pad(&#8216;$mc-&gt;delete() &#8217;, 60,
&#8216;_&#8217;).&#8220;n&#8221;;var_dump($val);?&gt;
<br />
是不是很简单，在实际应用中，通常会把数据库查询的结果集保存到 memcached 中，下次访问时直接从 memcached
中获取，而不再做数据库查询操作，这样可以在很大程度上减轻数据库的负担。通常会将 SQL 语句 md5() 之后的值作为唯一标识符
key。下边是一个利用 memcached 来缓存数据库查询结果集的示例（此代码片段紧接上边的示例代码）：
<br />
<br />
= &#8216;SELECT * FROM users&#8217;;$key = md5($sql);&nbsp;&nbsp; //memcached 对象标识符if (
!($datas = $mc-&gt;get($key)) ) {&nbsp;&nbsp;&nbsp; //&nbsp; 在 memcached
中未获取到缓存数据，则使用数据库查询获取记录集。&nbsp;&nbsp;&nbsp; echo &#8220;n&#8221;.str_pad(&#8216;Read datas from MySQL.&#8217;,
60, &#8216;_&#8217;).&#8220;n&#8221;;&nbsp;&nbsp;&nbsp; $conn = mysql_connect(&#8216;localhost&#8217;, &#8216;test&#8217;, &#8216;test&#8217;);&nbsp;&nbsp;&nbsp;
mysql_select_db(&#8216;test&#8217;);&nbsp;&nbsp;&nbsp; $result = mysql_query($sql);&nbsp;&nbsp;&nbsp; while ($row
= mysql_fetch_object($result))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $datas[] = $row;&nbsp;&nbsp;&nbsp; //&nbsp;
将数据库中获取到的结果集数据保存到 memcached 中，以供下次访问时使用。&nbsp;&nbsp;&nbsp; $mc-&gt;add($key, $datas);}
else {&nbsp;&nbsp;&nbsp; echo &#8220;n&#8221;.str_pad(&#8216;Read datas from memcached.&#8217;, 60,
&#8216;_&#8217;).&#8220;n&#8221;;}var_dump($datas);?&gt;可以看出，使用 memcached
之后，可以减少数据库连接、查询操作，数据库负载下来了，脚本的运行速度也提高了。
<br />
<br />
之前我曾经写过一篇名为《PHP 实现多服务器共享 SESSION 数据》文章，文中的 SESSION
是使用数据库保存的，在并发访问量大的时候，服务器的负载会很大，经常会超出 MySQL 最大连接数，利用
memcached，我们可以很好地解决这个问题，工作原理如下：
<br />
<br />
用户访问网页时，查看 memcached 中是否有当前用户的 SESSION 数据，使用 session_id()
作为唯一标识符；如果数据存在，则直接返回，如果不存在，再进行数据库连接，获取 SESSION 数据，并将此数据保存到 memcached
中，供下次使用； <br />
当前的 PHP 运行结束（或使用了 session_write_close()）时，会调用 My_Sess::write()
方法，将数据写入数据库，这样的话，每次仍然会有数据库操作，对于这个方法，也需要进行优化。使用一个全局变量，记录用户进入页面时的 SESSION
数据，然后在 write() 方法内比较此数据与想要写入的 SESSION 数据是否相同，不同才进行数据库连接、写入数据库，同时将
memcached 中对应的对象删除，如果相同的话，则表示 SESSION 数据未改变，那么就可以不做任何操作，直接返回了； <br />
那么用户 SESSION 过期时间怎么解决呢？记得 memcached 的 add() 方法有个过期时间参数 $exp
吗？把这个参数值设置成小于 SESSION 最大存活时间即可。另外别忘了给那些一直在线的用户延续 SESSION 时长，这个可以在
write() 方法中解决，通过判断时间，符合条件则更新数据库数据。 <br />
五、相关资源
<br />
<br />
memcached 官方网站
<br />
PHP memcached client
<br />
下载 memcached-client.php
<br />
http://www.dirk.sh/diary/216
<br />
Memcached 是一个非常优秀的缓存加速系统，和 Squid
的前端缓存加速不同，它是通过基于内存缓存对象来减少数据库查询的方式改善网站系统的反应，而其中最吸引人的一个特性就是支持分布式部署；也就是说可以在
一群机器上建立一堆 Memcached
服务，每个服务可以根据具体服务器的硬件配置使用不同大小的内存块，这样一来，理论上可以建立一个无限巨大的基于内存的 cache storage
系统。
<br />
<br />
Php 下的 Memcached 官方 API 是 memcache 这个包，前不久发布 2.0.0 stable
版本，关键的更新是增加了 addServer() 函数用于支持 Multiple servers with loadbalancing and
failover，在 FreeBSD 下安装： <br />
[root@trinity ~]# cd /usr/ports/databases/memcached/[root@trinity
~]# make install clean[root@trinity ~]# cd
/usr/ports/databases/pecl-memcache[root@trinity ~]# make install
clean另外一个号称更快的 API 包是 mcache，看作者的说明，是直接使用了 libmemcache，但在 FreeBSD
下目前还没有 Ports，需要源代码方式安装，具体可以参考 mcache 的说明。
<br />
<br />
一个简单的 PHP 脚本示例：
<br />
addServer('localhost', 11211);$memcache-&gt;addServer('localhost',
11212);if ($memcache) {&nbsp; $count =
intval($memcache-&gt;get('static_count'));&nbsp; $count ++;&nbsp;
$memcache-&gt;set('static_count', $count, 0, 30);&nbsp;
var_dump($memcache-&gt;get('static_count'));} else {&nbsp; echo "Connection
to memcached failed";}?&gt;但不管 Memcached
是一个多么优秀的东西，在没有合理的缓存策略（缓存什么东西？如何缓存？缓存时机？过期策略？）的情况下，只会被滥用，发挥不了真正的作用。构思
中&#8230;...
<img src ="http://www.blogjava.net/conans/aggbug/292623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-08-26 11:47 <a href="http://www.blogjava.net/conans/articles/292623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Memcached使用点滴</title><link>http://www.blogjava.net/conans/articles/292622.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 26 Aug 2009 03:43:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/292622.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我对于Memcached的接触，还是在去年看了CSDN的一系列国外大型网站架构设计而开始的。最初的时候只是简单的封装了Memcached Java版的客户端，主要是对于配置的简化以及Memcached多点备份作了一些工作，然后就作为ASF的组件一部分提供给其他Team使用。其实看过Memcached Java客户端代码的人就会了解其实客户端的事情很简单，就是要有一套高性能的Socket通信框架以及...&nbsp;&nbsp;<a href='http://www.blogjava.net/conans/articles/292622.html'>阅读全文</a><img src ="http://www.blogjava.net/conans/aggbug/292622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-08-26 11:43 <a href="http://www.blogjava.net/conans/articles/292622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>善用Google日历，让事情做得更高效</title><link>http://www.blogjava.net/conans/articles/251400.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 15 Jan 2009 02:53:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/251400.html</guid><description><![CDATA[<p>以前我总是以为脑袋够用，从来不用备忘、日程等工具。但事实上我太高估自己的能力，一个日程表、一个事项提醒，或者一个todo list都是十分有用的。在<a href="http://lifehacker.com/378062/five-best-gtd-applications">Lifehacker的投票</a>里，人们认为<strong>最有用的GTD(Getting Things Done)工具是：笔和纸</strong>。除了笔和纸之外，<a href="https://www.google.com/calendar/">Google日历</a>是我认为目前最好一个日程管理服务，或许你正在用，如果你了解下面的一些小技巧，你会用的更舒服。</p>
<p>
<p><img height="288" alt="" src="http://img.cnbeta.com/newsimg/090114/1800240333026621.jpg" width="514" /></p>
<p>&nbsp;</p>
<p>昨天在<a href="http://twitter.com/jason5ng32">twitter</a>里做了个小小的调查，使用Google日历的朋友不少，大多数人都会用到其中一个功能：<strong>短信提醒</strong>。</p>
<p>这是个非常有效的事项提醒方式。</p>
<h2>一、连接与外观</h2>
<blockquote>
<h3>1、https加密访问</h3>
<blockquote>
<p>Google日历支持https方式连接，建议大家都使用这种方式。当你在Google因搜索低俗内容被断开连接后，使用http方式是无法连接Google日历的。<a title="关于Gmail你可能不知道的8件事" href="http://www.kenengba.com/post/408.html">Gmail也有https方式</a>。</p>
<p>事实上，能用https的服务都建议大家使用这种方式，<a title="在这个互联网你该相信谁？" href="http://www.kenengba.com/post/533.html">这个互联网不可靠</a>，你永远不知道什么时候会被低俗。</p>
</blockquote>
<h3>2、拖曳选择日期区间</h3>
<blockquote>
<p>你可以使用拖曳日期的方式选择日程显示区间：</p>
<p><img height="165" alt="" src="http://img.cnbeta.com/newsimg/090114/1800251181313064.jpg" width="171" /></p>
</blockquote>
<h3>3、设定个性化日期区间</h3>
<blockquote>
<p>当然，除了拖曳选择日期区间外，你还可以在设置里设置&#8220;自定义视图&#8221;显示的日期数目。</p>
</blockquote>
<h3>4、给Google日历换个皮肤</h3>
<blockquote>
<p>觉得Google日历太丑了？有时我也有这样的感觉，你可以使用Better GCal Firefox扩展使其变得漂亮，总体外观如下：</p>
</blockquote>
<p><img height="321" alt="" src="http://img.cnbeta.com/newsimg/090114/18002521671284260.jpg" width="484" /></p>
</blockquote>
<h2>二、同步日历</h2>
<p>一个好的日程表应该具有导出功能，也就是能与其它日程管理软件/服务同步。</p>
<blockquote>
<h3>1、与电脑软件同步</h3>
<blockquote>
<p>你可以在<a href="http://www.google.com/support/calendar/bin/topic.py?topic=15285">这里</a>看到将Google日历导出到Outlook等软件和导入日历到Google日历的步骤。</p>
<p>如果你使用的是MS Outlook，你还可以使用专用的软件来同步：<a href="http://dl.google.com/googlecalendarsync/GoogleCalendarSync_Installer.exe" target="_blank" rel="nofollow">Google Calendar Sync</a></p>
</blockquote>
<h3>2、同步到手机</h3>
<blockquote>
<h4>（1）S60系列</h4>
<blockquote>
<p>如果你在用S60系列手机，你可以用<a href="http://www.gcalsync.com/">GcalSync</a>来将手机日程与Google日历同步，首先你需要在手机上安装GcalSync软件。</p>
<p>安装软件后设置好用户名和密码即可。</p>
</blockquote>
<h4>（2）iPhone</h4>
<blockquote>
<p>对于iPhone来说，可以使用一款名为NemusSync的软件，我目前正在使用，同步效果很理想。</p>
</blockquote>
<h4>（3）其它手机</h4>
<blockquote>
<p>如果你的手机既不是S60也不是iPhone，可以考虑使用<a href="http://www.goosync.com/">GooSync服务</a>。</p>
<p>首先你需要在GooSync注册账户，导入你的账户信息，然后再在手机上安装GooSync的软件。</p>
<p><strong>GooSync不但能同步日程表，还可以同步Email联系人等。</strong></p>
</blockquote></blockquote>
<h3>3、结合Remember the Milk</h3>
<blockquote>
<p>Remember the Milk是最好的Todo List服务之一，你可以在Google日历里将RTM导入，方法是：</p>
<p>将下面URL的日历添加到Google日历，接着输入RTM的用户信息：</p>
<p><a href="http://www.rememberthemilk.com/services/modules/googlecalendar/ics.rtm">http://www.rememberthemilk.com/services/modules/googlecalendar/ics.rtm</a></p>
</blockquote></blockquote>
<h2>三、日历通知</h2>
<blockquote>
<h3>1、短信通知</h3>
<blockquote>
<p>大多数人都会使用这种通知方式。Google日历的短信通知方式是免费的，支持大多数手机号，你可以在Google日历设置里添加手机号，在添加事项后设置短信提醒。</p>
<p><img height="115" alt="" src="http://img.cnbeta.com/newsimg/090114/1800263106004717.jpg" width="351" /></p>
<p>让我好奇的是，每次SMS通知的SP号都是不一样的。</p>
</blockquote>
<h3>2、团队日程群发短信</h3>
<blockquote>
<p>如果你在为一个团队管理日程，你希望每个人都收到短信提醒，可以用以下的方法：</p>
<blockquote>
<p>（1）让每个人注册Google日历，并设置好手机号</p>
<p>（2）添加一个团队日历，同时邀请所有团队成员（Email方式）</p>
<p>（3）将事项设置为短信提醒</p>
</blockquote>
<p><strong>这主要是用于团队事物提醒，最好别滥用在群发短信上。</strong></p>
</blockquote>
<h3>3、免费天气预报短信</h3>
<blockquote>
<p>既然Google日历支持导入日历又支持短信提醒，那是否可以导入一个天气日历，然后我们就可以接收免费的天气预报短信呢？</p>
<p>能，具体请移步：<a title="免费天气预报短信" href="http://www.kenengba.com/post/518.html">免费接收天气预报短信的两种方式</a></p>
</blockquote></blockquote>
<h2>四、操作技巧</h2>
<blockquote>
<p>1、快捷键</p>
<blockquote>
<p>或许你不知道，Google日历是支持快捷键操作的，英文版的Google日历比中文版有更多的快捷键。和在Google Reader和Gmail的快捷键一样，J,K分别是上下操作。C(compose)是新建日程。</p>
<p>当你忘记快捷键时，同样可以输入?（Ctrl+/）来查看快捷键提示。</p>
<p><img height="246" alt="" src="http://img.cnbeta.com/newsimg/090114/18002641623503870.jpg" width="387" /></p>
</blockquote>
<p>2、拖曳日程</p>
<blockquote>
<p>Google日历支持拖曳日程，你可以将某个日程拖到另外一天或另一时段（月视图不可拖曳改变时间）：</p>
<p><img height="95" alt="" src="http://img.cnbeta.com/newsimg/090114/18002651295747429.jpg" width="250" /></p>
</blockquote></blockquote>
<h2>五、日程共享</h2>
<blockquote>
<h3>1、日历分享</h3>
<blockquote>
<p>事实上在说到&#8220;团队短信提醒&#8221;时已提到日历分享，你可以与特定的人分享这个日历（通过email），也可以将这个日历设置为公开，这样所有人都可以导入你的日历。</p>
<p><img height="103" alt="" src="http://img.cnbeta.com/newsimg/090114/18002761413052094.jpg" width="280" /></p>
</blockquote>
<h3>2、嵌入到网页</h3>
<blockquote>
<p>这是个十分有用的功能，之前我做的奥运日程表就是使用了Google日历的网页嵌入功能，具体操作可以参考嵌入<a href="http://www.kenengba.com/post/484.html">奥运日程</a>的文章。</p>
</blockquote>
<h3>3、订阅日历</h3>
<blockquote>
<p>既然日历可以分享给别人导入，你同样也可以导入别人的日历。你可以直接从URL里添加一个新日历，也可以在日历搜索里搜索日历。</p>
<p>比如我，搜索到了F1 2009年的赛历，这样我就不会错过今年的F1比赛了。</p>
</blockquote></blockquote>
<h2>六、其它</h2>
<blockquote>
<h3>1、RSS订阅日历</h3>
<blockquote>
<p>和前面提到的&#8220;订阅日历&#8221;不一样，这里的订阅是用RSS阅读器来订阅日历。如果你是一个天天只生活在阅读器里的人，你可以订阅任何公开的日历。</p>
<p>每个公开的日历都有唯一的RSS订阅地址。<strong>这种方式会导致日程滞后，因为阅读器抓取频率是固定的，不是无间断扫描。</strong></p>
</blockquote>
<h3>2、作为日记使用</h3>
<blockquote>
<p>将Google日历当做日记来使用是个不错的想法，你可以新建一个&#8220;日记&#8221;日历，然后每天在这个日历里写上日记。</p>
<p>有什么比这样写私人日记更方便？</p>
</blockquote>
<h3>3、使用Twitter更新日程</h3>
<blockquote>
<p><a title="Twitter高级应用" href="http://www.kenengba.com/post/587.html">Twitter进阶手册</a>里应该添加这个项目，这实在太有用了。</p>
<p>打开<a href="http://twittercal.com/">http://twittercal.com</a>，注册账号后在twitter follow twittercal机器人，以后将日程信息以私信的形式发给twittercal机器人，日程就会被添加到Google日历。</p>
</blockquote></blockquote>
<h2>七、关于GTD</h2>
<blockquote>
<p><strong>GTD是一门高深的学问，如何将事情以最高效并且不遗漏地做好是一件不容易的事。不要盲目地认为大脑可以记录下一切，这是很难的，尤其是一些突如其来的想法。</strong></p>
<p><strong>我的做法是，随身带备笔和纸，外加使用Google日历与手机日程同步。</strong></p>
<p><img height="83" alt="" src="http://img.cnbeta.com/newsimg/090114/18002771039378525.jpg" width="498" /></p>
<p>有时我会有突然的想法，如果当时我在线，我会用Gtalk将它发送到我一个备用邮箱；如果不在线，如果没有图像或公式，我会记在手机上，然后同步到日历；如果有图的话，那笔和纸是必须的。</p>
<p>一旦有什么事情要在半天后做，我一定会添加到Google日历，我已经不再相信我的大脑了，在这个信息过载的世界，我无法依靠大脑去记住一切。我认为，凡是能快速查询到的信息，都不必记在大脑里。</p>
<p>我很少使用软件来记录日程，一般都使用在线服务</p>
</blockquote>
<img src ="http://www.blogjava.net/conans/aggbug/251400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-01-15 10:53 <a href="http://www.blogjava.net/conans/articles/251400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>KITE: Keynote的互联网测试环境</title><link>http://www.blogjava.net/conans/articles/210937.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 26 Jun 2008 11:57:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210937.html</guid><description><![CDATA[<h4 class="copyright">声明：JavaEye新闻文章的版权属于JavaEye网站所有，严禁任何网站转载本文，否则必将追究法律责任！</h4>
<div id="news_content">Keynote发布了名叫<a href="http://blogs.keynote.com/the_watch/2008/06/announcing-kite.html" target="_blank">KITE</a>的互联网测试环境。 <br />
<br />
<img src="http://kite.keynote.com/images/logo.jpg" _counted="undefined"  alt="" /> <br />
<br />
KITE是一款免费使用的软件，在<a href="http://kite.keynote.com/" target="_blank">http://kite.keynote.com</a>注册，可在<a href="http://kite.keynote.com/download-center.php" target="_blank">这里</a>下载使用。KITE是一个新的基于桌面的测试软件，编辑和分析网站的性能，给出可视化分析结果，能提供性能标准给整个web应用生命周期组，包括开发者，QA，性能分析和Web操作部门。 <br />
<br />
优势包括： <br />
<br />
1。测试Scripts操作基于DOM动作，比如创建DOM元素，创建符合某种特殊格式的DOM元素。 <br />
<br />
2。客户端程序展示可视的HTTP属性链接 <br />
<br />
3。基于Keynote支持，测试能够在全球5个城市同时进行。 <br />
<br />
4。完全免费。 <br />
<br />
<img src="http://ajaxian.com/wp-content/images/tweetwheelkite.gif" _counted="undefined"  alt="" /></div>
<img src ="http://www.blogjava.net/conans/aggbug/210937.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-26 19:57 <a href="http://www.blogjava.net/conans/articles/210937.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>系统构建网络安全体系（转）</title><link>http://www.blogjava.net/conans/articles/210932.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 26 Jun 2008 11:54:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210932.html</guid><description><![CDATA[<div class="blog_content">
<p>据最新的互联网安全威胁报告显示，混合式网络威胁日益增多。目前全球每20秒就发生一次计算机入侵事件,Windows系统和组件的漏洞增多以及严重信息系统漏洞的不断涌现，使得<a href="http://www.qqread.com/tag/1962/index.html" target="_blank">网络安全</a> 成为亟待解决的问题。如何保护企业的机密信息不受黑客和工业间谍的入侵，已成为政府机构、电信<a href="http://www.qqread.com/z/telecom/c/index.html" target="_blank">运营商</a> 、企事业单位信息化健康发展需首要考虑的问题。 </p>
<p>&nbsp;&nbsp;&nbsp; 由于层出不穷的病毒攻击着<a href="http://www.qqread.com/tag/3901/index.html" target="_blank">网络系统</a> 中的各级设备，而各种病毒、CIH、冲击波等更是侵犯着网络中的基础设施，这些情况迫使<a href="http://www.qqread.com/tag/2972/index.html" target="_blank">安全问题</a> 解决策略不能再局限于某一节点、某一设备上，而是要从系统的高度出发，全面考虑全网的设施，全新认识<a href="http://www.qqread.com/tag/2958/index.html" target="_blank">安全防护</a> 。对于电信运营商而言，不仅要从物理层保证传输安全，而且还要站在网络层次的高度，重新看待和分析网络安全，在全网架构中确定重点的防范区域，分层次、分阶段的布设安全措施。</p>
<p>&nbsp;&nbsp;&nbsp; 一、传统电信网的安全</p>
<p>&nbsp;&nbsp;&nbsp; 传统电信网是基于连接的物理通信网络，且是封闭的网络。同时,传统用户终端也是模拟终端，如电话机、传真机等是不带智能的，这就使得相应业务完全由运营商控制，即控制和承载不分离，网络面临的安全的复杂性也就大大低于现有网络。</p>
<p>&nbsp;传统电信网解决通信安全的主要目的是在物理传输上防止窃听及数据传输问题，对数据传输其主要的安全保护措施是密码技术，不涉及OSI或<a href="http://www.qqread.com/z/tcp_ip/index.html" target="_blank">TCP/IP</a> 的上层<a href="http://www.qqread.com/z/protocol/index.html" target="_blank">协议</a> 。</p>
<p>&nbsp;&nbsp;&nbsp; 二、现有网络的安全</p>
<p>&nbsp;&nbsp;&nbsp; 近年来由于互联网的快速发展，电信网的分组数据业务呈爆炸性增长，基于TDM的PSTN话音网和分组交换数据网呈现融合趋势，即电信网与互联网的融合，形成可以传递话音和数据等综合业务的新一代网络。</p>
<p>&nbsp;&nbsp;&nbsp; 由于互联网是一个IP网络，它是开放且无连接性的，具有边界和路径不确定性：从用户源主机到另一个目的主机可能存在多条路径，一个主机可能是两个不同网络中的一个中转点。因此，一个网络中的资源可由另一网中的用户访问。这样，一些未经授权的非法用户可能就会给网络安全构成严重的威胁。</p>
<p>&nbsp;&nbsp;&nbsp; 网络安全已经成为互联网发展过程中不容忽视的问题。尤其是为了减缓<a href="http://www.qqread.com/z/tech/ip/index.html" target="_blank">IP地址</a> 匮乏，引进了<a href="http://www.qqread.com/keys/nat/index.html" target="_blank">NAT</a> 技术，现在大部分诸如企业网、<a href="http://www.qqread.com/z/network/xyw/index.html" target="_blank">校园网</a> 等的<a href="http://www.qqread.com/z/network/29/index.html" target="_blank">局域网</a> 都采用了这种NAT技术，这种技术破坏了端到端的基本原则，在很大程度上破坏了互联网的授权和鉴定机制。</p>
<p>&nbsp;&nbsp;&nbsp; 三、网络安全体系结构</p>
<p>&nbsp;&nbsp;&nbsp; 这里针对互联网络系统实际运行TCP／IP协议模型来分析。TCP／IP 协议模型网络安全贯穿于信息系统的四个层次，即<a href="http://www.qqread.com/tag/3877/index.html" target="_blank">网络接口</a> 层、网络层、传输层、应用层。为此基于TCP／IP分层模型的网络安全服务也是分层的，相应的不同层次的网络服务也是不同的，需要分层进行<a href="http://www.qqread.com/z/sys/safe-seting/index.html" target="_blank">配置</a> 。下表是TCP／IP分层模型中提供的的网络安全服务 (Y表示服务选项并入该层的标准之中，空格表示不提供)。</p>
<p align="center"><a href="http://www.qqread.com/ArtImage/20060511/fu12_1.gif" target="_blank"><img alt="系统构建网络安全体系" src="http://www.qqread.com/ArtImage/20060511/fu12_1.gif" width="590" border="0" _counted="undefined" /> 点击查看大图</a> </p>
<p>&nbsp;&nbsp;&nbsp; 1.网络接口层安全</p>
<p>&nbsp;&nbsp;&nbsp; 网络接口层是TCP／IP的最低层，包括OSI的物理层、<a href="http://www.qqread.com/tag/1855/index.html" target="_blank">数据链路层</a> 。网络接口层有两种类型：第一种是设备驱动程序(如局域网的网络接口)；第二种是含自身数据链路协议的复杂子系统(如X．25中的网络接口)。为保证通过网络链路传送的数据不被窃听，主要采用划分<a href="http://www.qqread.com/z/network/vlan/index.html" target="_blank">VLAN</a> 、加密通信(远程网)等手段进行加密。</p>
<p>&nbsp;&nbsp;&nbsp; 对于通过使用<a href="http://www.qqread.com/z/network/vpn/index.html" target="_blank">VPN</a> 业务连接多个私有地点的组织应该使用NAT、<a href="http://www.qqread.com/z/soft/firewall/index.html" target="_blank">防火墙</a> 和<a href="http://www.qqread.com/tag/1824/index.html" target="_blank">数据加密</a> 技术。在VPN拓扑结构中，私有数据在公共网络上传送，因此加密是必须的。第2层隧道协议(L2TP)就是互联网工程任务组(IETF)针对在公共网络上用隧道传送私有数据而制定的标准。作为VPN业务中的一种，光<a href="http://www.qqread.com/tag/2163/index.html" target="_blank">虚拟专用网</a> （OVPN）是下一代光传送网-智能光网络最有潜力的增值业务。OVPN的关键技术包括：安全隧道与信息<a href="http://www.qqread.com/tag/3328/index.html" target="_blank">加密技术</a> ，即使用加密与封装相结合的技术对用户数据进行安全保护；在VPN用户访问<a href="http://www.qqread.com/tag/3915/index.html" target="_blank">网络资源</a> 及管理员对VPN系统进行管理之前，采用用户认证技术进行<a href="http://www.qqread.com/tag/3680/index.html" target="_blank">身份认证</a> ；<a href="http://www.qqread.com/z/network/acl/index.html" target="_blank">访问控制</a> 技术提供细粒度的访问控制功能以实现对用户信息资源的保护。</p>
<p>&nbsp;&nbsp;&nbsp; 使用光虚拟专用网不仅具有共享的经济性、灵活性、可靠性和可扩展性等特点，更重要的是它在光层的安全性受到电信运营商的重视，这对于客户来说支出更少，而对于运营商来说则有更多的收入、更安全的网络。可以说，OVPN服务对于用户和运营商来说是一种双赢的选择方案，在将来的智能光网络领域有着广泛的应用前景。</p>
<p>&nbsp;&nbsp;&nbsp; 2.网络层安全</p>
<p>&nbsp;&nbsp;&nbsp; 网络层安全即IP层安全性，它的主要优点是其透明性，也就是说，安全服务的提供不需要应用程序，也不需要对其他通信层次和网络部件做任何改动。最主要缺点的是IP层一般对属于不同<a href="http://www.qqread.com/z/windows/process/index.html" target="_blank">进程</a> 的包不作区别。对所有去往同一地址的包，它将按照同样的加密密钥和访问控制策略来处理，这将使得网络安全性能下降。针对面向主机密钥分配的这些问题，RFCl825推荐使用面向用户的密钥分配，其中，不同的连接会得到不同的加密密钥。但是，面向用户的密钥分配需要对相应的<a href="http://www.qqread.com/tag/1182/index.html" target="_blank">操作系统</a> 内核作比较大的改动。 </p>
<p>&nbsp;&nbsp;&nbsp; IP层非常适合提供基于主机的安全服务，相应的安全协议可以用来在互联网上建立安全的IP通道和<a href="http://www.qqread.com/tag/2162/index.html" target="_blank">虚拟专网</a> 。例如，利用它对IP包的加密和解密功能，可以简捷地强化防火墙系统的防卫能力。</p>
<p>&nbsp;&nbsp;&nbsp; 网络层的安全性问题核心在于网络是否能得到控制，目标网站通过对来源IP进行分析，便能够初步判断来自这一IP的数据是否安全，是否会对本网络系统造成危害，来自这一IP的用户是否有权使用本网络的数据。一旦发现某些数据来自不可信任的IP地址，系统便会自动将这些数据阻挡在系统之外，并且大多数系统能够自动记录那些曾经造成过危害的IP地址，使它们的数据无法造成第二次危害。网络层主要的<a href="http://www.qqread.com/keys/safetech/index.html" target="_blank">安全技术</a> 包括：</p>
<p>&nbsp;&nbsp;&nbsp; (1)防火墙</p>
<p>&nbsp;&nbsp;&nbsp; 防火墙是建立在内外网络边界上的过滤封锁机制。内部网络被认为是安全和可信赖的，而外部网络(通常是互联网)被认为是不安全和不可信赖的。防火墙的作用是防止不希望的、未经授权的通信进入被保护的内部网络，通过边界控制强化内部网络的<a href="http://www.qqread.com/tag/2955/index.html" target="_blank">安全策略</a> 。 </p>
<p>&nbsp;&nbsp;&nbsp; 防火墙对于解决一些机构网络边界安全问题起到了比较好的效果，应用很广泛，但它只能是网络安全措施的一个组成部分，而不能解决所有的网络安全问题。 </p>
<p>&nbsp;&nbsp;&nbsp; (2)IP安全协议(IPSec)</p>
<p>&nbsp;&nbsp;&nbsp; IP安全协议(IPSec)是一组提供数据保密性、数据完整性和对IP层的参与各方进行<a href="http://www.qqread.com/tag/3682/index.html" target="_blank">身份验证</a> 的公开标准。IPSec已经获得行业的认可，客户也要求所购买的互联网产品中包含对它的支持。IPSec使用认证头部(AH)和安全内容封装(ESP)两种机制，前者提供认证和数据完整性，后者实现通信保密。</p>
<p>&nbsp;&nbsp;&nbsp; IPSec使得一个系统能够选择安全协议和算法，并且建立密钥。互联网密钥交换(IKE)协议提供了对IPSec同等各方的身份验证。使用IKE还可以对IPSec密钥和其他安全性相关措施进行协商。IKE主要使用以下技术：</p>
<p>&nbsp;&nbsp;&nbsp; ① DES——用来对数据包数据进行加密；</p>
<p>&nbsp;&nbsp;&nbsp; ② Diffie-Hellman——用来建立一个共享的、保密的会话密钥；</p>
<p>&nbsp;&nbsp;&nbsp; ③ Message Digest 5(MD5)——一个对数据包数据进行身份验证的哈希算法；</p>
<p>&nbsp;&nbsp;&nbsp; ④ Secure Hash Algorithm(SHA) ——一个对数据包数据进行身份验证的哈希算法；</p>
<p>&nbsp;&nbsp;&nbsp; ⑤ RSA encryptednonces——提供否认功能；</p>
<p>&nbsp;&nbsp;&nbsp; ⑥RSA签名——提供认可功能。 </p>
<p>&nbsp;&nbsp;&nbsp; (3) <a href="http://www.qqread.com/z/network/ids/index.html" target="_blank">入侵检测</a> 技术</p>
<p>&nbsp;&nbsp;&nbsp; ICSA(入侵检测系统论坛)对入侵检测技术的定义是：通过从<a href="http://www.qqread.com/tag/3318/index.html" target="_blank">计算机网络</a> 或计算机系统中的若干关键点收集信息并对其进行分析，从中发现网络或系统中是否有违反安全策略的行为和遭到袭击迹象的一种安全技术。</p>
<p>&nbsp;&nbsp;&nbsp; 入侵检测技术是动态安全技术中最为核心的技术之一。传统的操作系统加固技术和防火墙隔离技术等都是静态安全防御技术，对网络环境下日新月异的攻击手段缺乏主动的反应。入侵检测作为一种积极主动的安全防护技术，从网络安全立体纵深、多层次防御的角度出发，在不影响<a href="http://www.qqread.com/z/network/test/index.html" target="_blank">网络性能</a> 的情况下能对网络进行监测，提供了对内部攻击、外部攻击和误操作的实时保护，在网络系统受到危害之前拦截和响应入侵。</p>
<p>&nbsp;&nbsp;&nbsp; 目前，利用最新的可适应<a href="http://www.qqread.com/tag/3833/index.html" target="_blank">网络安全技术</a> 和 P2DR(PolicyProtectionDetectionResvonse)安全模型，已经可以深入地研究入侵事件、入侵手段本身及被入侵目标的漏洞等。入侵检测技术通过对入侵行为的过程与特征的研究，使安全系统对入侵事件和入侵过程能做出实时响应。入侵检测技术的一个发展趋势是将它集成到路由器或<a href="http://www.qqread.com/tag/1766/index.html" target="_blank">三层交换机</a> 中，在实现网络安全的过程中入侵检测技术执行的任务包括：监视、分析用户及系统活动；系统构造和弱点的审计；识别、反映已知进攻的活动模式并向相关人士报警；异常行为模式的统计分析；评估重要系统和数据文件的完整性；操作系统的审计跟踪管理，并识别用户违反安全策略的行为。</p>
<p>&nbsp;&nbsp;&nbsp; 3.传输层安全</p>
<p>&nbsp;&nbsp;&nbsp; 传输层的脆弱性已经成为<a href="http://www.qqread.com/keyword/net-protocol.html" target="_blank">网络协议</a> 攻击的主要突破口之一，其漏洞如下：</p>
<p>&nbsp;&nbsp;&nbsp; ① <a href="http://www.qqread.com/tag/2844/index.html" target="_blank">TCP连接</a> 的建立与终止。TCP连接的建立与断开机制保证了传输的可靠性与速度，但是在连接建立过程完成之后，<a href="http://www.qqread.com/tag/3159/index.html" target="_blank">服务器端</a> 不再验证连接的另一方是不是合法的用户，这种脆弱性的直接后果是连接可能被窃取。</p>
<p>&nbsp;&nbsp;&nbsp; ② TCP连接请求对队列的处理方法看起来很适用于连接的实际情况，但是很容易出现以下现象：如果某一用户不断地向服务器某一端口发送申请TCP连接的SYN 请求包，但不对服务器的SYN包发回ACK确认信息，则无法完成连接。当未完成的连接填满传输层的队列时，它不再接受任何连接请求，包括合法的连接请求，这样就可能使服务器端口服务挂起。</p>
<p>&nbsp;&nbsp;&nbsp; ③TCP连接的坚持。TCP连接仍旧能保持的特性会造成当TCP连接上很长时间内无数据被传送时TCP连接资源的浪费。毕竟服务器某个端口可以存在的最大连接数有限，保持着大量不<a href="http://www.qqread.com/tag/3038/index.html" target="_blank">传输数据</a> 的连接将极大地降低服务器性能，而且在服务器的两次探测之间，可能导致TCP连接被窃取，使得原来与服务器连接的机器死机或重启。</p>
<p>&nbsp;&nbsp;&nbsp; 由于TCP／IP协议本身非常简单，没有加密、身份认证等安全特性，因此要向上层应用提供安全通信的机制就必须在TCP之上建立一个安全通信层次。传输层网关就是在两个通信节点之间代为传递TCP连接并进行控制，这个层次一般称作传输层安全。最常见的传输层安全技术有<a href="http://www.qqread.com/z/network/ssl/index.html" target="_blank">SSL</a> （安全套接层协议）、SOCKS和安全RPC等。同网络层安全机制相比，传输层安全机制的主要优点是它提供基于进程对进程(而不是主机对主机)的安全服务和加密传输信道，利用公钥体系进行身份认证、安全强度高、支持用户选择的加密算法。这一成就如果再加上应用级的安全服务，就可以提供更加安全可靠的安全性能。</p>
<p>&nbsp;&nbsp;&nbsp; 4.应用层安全</p>
<p>&nbsp;&nbsp;&nbsp; 应用层的缺陷主要集中在R系列命令中(rcp、rsh、rlogin等)，这些命令是基于可信任主机之间的关系而设置的方便用户登录的一种方法，可信任主机不需要口令也可以通过R系列命令登录进入目标系统。</p>
<p>&nbsp;&nbsp;&nbsp; 一般说来，在应用层提供安全服务有下面几种可能的做法。首先是对每个应用(及应用协议)分别进行修改和扩展，加入新的安全功能。一些重要的TCP／IP应用已经这样做了。例如，在RFCl421～1424中，IETF规定了私用强化邮件(PEM)来为基于SMTP的<a href="http://www.qqread.com/z/mail/safe/index.html" target="_blank">电子邮件</a> 系统提供安全服务，应用层对防止系统遭病毒侵入和<a href="http://www.qqread.com/tag/1416/index.html" target="_blank">黑客攻击</a> 都有极其重要的作用。另外，应用层还可以使用应用平台提供的安全服务，如采用通信内容安全保护、通信双方的认证、审计等手段来保证基本安全。</p>
<p>&nbsp;&nbsp;&nbsp; 四、结束语</p>
<p>&nbsp;在安全性设计中包含的任务与网络总体设计所包含的任务是一致的：分析网络<a href="http://www.qqread.com/tag/2973/index.html" target="_blank">安全需求</a> 和目标，对其复杂性作出折中，因为任何网络都不会有绝对的安全，安全的保护和策略越复杂，则投入的网络运营成本越高。因此，找到两者的平衡点，制定出一种合适的安全策略是非常必要的。</p>
</div>
<img src ="http://www.blogjava.net/conans/aggbug/210932.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-26 19:54 <a href="http://www.blogjava.net/conans/articles/210932.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DVD转AVI</title><link>http://www.blogjava.net/conans/articles/210683.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 25 Jun 2008 13:40:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210683.html</guid><description><![CDATA[用MediaCoder转换, <br />
它是一个免费的通用音频/视频批量转码工具，它将众多来自开源社区的优秀音频视频编解码器和工具整合为一个通用的解决方案，它可以将音频、视频文件在各种格式之间进行转换。 <br />
特点聚焦 <br />
直接、批量地在众多音频视频压缩格式和容器格式之间进行转换 <br />
完全控制转码过程和目标文件的各个参数 <br />
针对各种目标设备的专用界面（插件机制） <br />
纯绿色软件，无需安装任何媒体播放器或编码器，不在系统中注册任何组件 <br />
典型应用 <br />
提高压缩率/减小文件尺寸 <br />
转换至可在各种影音设备上播放的文件，如MP3播放器、MP4播放器、手机、PDA、PSP、VCD/DVD播放机 <br />
提取视频文件中的音轨 <br />
压缩和保存影音光碟 <br />
<br />
<a href="http://mediacoder.sourceforge.net/download_zh.htm" target="_blank">http://mediacoder.sourceforge.net/download_zh.htm</a> <br />
网站里有 教程 <br />
<a href="http://www.mediacoder.cn/wiki/index.php?title=%E9%A6%96%E9%A1%B5#MediaCoder.E7.94.A8.E6.88.B7.E6.96.87.E6.A1.A3" target="_blank">http://www.mediacoder.cn/wiki/index.php?title=%E9%A6%96%E9%A1%B5#MediaCoder.E7.94.A8.E6.88.B7.E6.96.87.E6.A1.A3</a> <br />
<br />
推荐使用 稳定版</ca><br />
<br />
<br />
<br />
<br />
========================================================================================================<br />
<br />
1. RM to AVI MPEG WMV VCD SVCD DVD Converter V2.8 <br />
<br />
功能强大，易于使用的用来转换RM格式文件到AVI、WMV、 <br />
<a href="http://www.skycn.com/soft/17254.html" target="_blank">www.skycn.com/soft/17254.html</a> <br />
<br />
<br />
2. Aare AVI to VCD DVD SVCD MPEG Converter 6.1 <br />
<br />
AareAVItoVCD/DVD/SVCDConverter是一个基于Windows的视频转换程序,程序可以帮助你将AV <br />
<a href="http://www.onlinedown.net/soft/11787.htm" target="_blank">www.onlinedown.net/soft/11787.htm</a> <br />
<br />
<br />
3. RM to AVI MPEG WMV VCD SVCD DVD Converter V2.80 汉化版 <br />
<br />
功能强大，易于使用的用来转换RM格式文件到AVI、WMV、 <br />
<a href="http://www.skycn.com/soft/17253.html" target="_blank">www.skycn.com/soft/17253.html</a> <br />
<br />
<br />
4. Flash转换王 6.55 Build 590 <br />
<br />
将Flash的SWF动画转换为VCD/SVCD/DVD/AVI等视频格式的转换工具 <br />
download.pchome.net/multimedia/video/18838.html <br />
<br />
<br />
5. RM转换精灵 7.1.2 <br />
<br />
RM和RMVB文件转换到AVI、DVD、VCD、SVCD、MPEG格式的工具 <br />
download.pchome.net/multimedia/video/19129.html <br />
<br />
<br />
6. Zealot AVI to VCD SVCD DVD Converter 2.8.0 <br />
<br />
一款功能强大的视频文件格式转换工具 <br />
download.pchome.net/multimedia/video/15889.html <br />
<br />
<br />
7. #1 DVD Ripper 2.2.0 <br />
<br />
轻松将DVD影片备份为VCD(MPEG1)或SVCD格式(MPEG2),也可以转换为AVI <br />
download.pchome.net/multimedia/dvd/dvdripper/2895.html <br />
<br />
<br />
8. RM to AVI MPEG WMV VCD SVCD DVD Converter 2.8.0 <br />
<br />
转换RM格式到AVI、MPEG、WMV、VCD、SVCD和DVD格式的工具 <br />
download.pchome.net/multimedia/video/16469.html <br />
<br />
<br />
9. Avi2Dvd 0.4.3 beta <br />
<br />
一款免费的将avi/mkv/ogm转换为vcd/svcd/dvd格式的工具 <br />
download.pchome.net/multimedia/video/19517.html <br />
<br />
<br />
10. Flash转换王 5.92 Build 410 <br />
<br />
将Flash的SWF动画转换为VCD/SVCD/DVD/AVI等视频格式的转换工具 <br />
download.pchome.net/design/animation/18838.html <br />
<br />
<br />
11. AVOne - RM to AVI/DVD/VCD/SVCD/MPEG Converter V3.49 <br />
<br />
是一款视频转换工具，能将RM/RAM/RMVB文件转变为AVI， <br />
<a href="http://www.skycn.com/soft/13998.html" target="_blank">www.skycn.com/soft/13998.html</a> <br />
<br />
<br />
12. Aare AVI to VCD/DVD/SVCD Converter 5.0 汉化补丁 <br />
<br />
AareAVItoVCD/DVD/SVCDConverter是一个基于Windows的视频转换程序,程序可以帮助你将AV <br />
<a href="http://www.onlinedown.net/soft/23247.htm" target="_blank">www.onlinedown.net/soft/23247.htm</a> <br />
<br />
<br />
13. RM to AVI VCD SVCD DVD MPEG Converter V3.2 <br />
<br />
Rm to AVI VCD SVCD DVD Converter是影片转档的工具， <br />
<a href="http://www.skycn.com/soft/15306.html" target="_blank">www.skycn.com/soft/15306.html</a> <br />
<br />
<br />
14. 1Click DVD to DivX AVI 1.21 <br />
<br />
1ClickDVDtoDivxxVidAvi是一个将DVD转换成Divx,xVid和Avi文件的工具，可以对整个DVD或 <br />
<a href="http://www.onlinedown.net/soft/23708.htm" target="_blank">www.onlinedown.net/soft/23708.htm</a> <br />
<br />
<br />
15. WMV to AVI MPEG WMV VCD SVCD DVD Converter 2.8.0 <br />
<br />
功能强大的视频文件转换工具 <br />
download.pchome.net/multimedia/video/17914.html <br />
<br />
<br />
16. Aurora Video VCD/SVCD/DVD Converter&amp;Creator V5.01 <br />
<br />
一款视频文件转换工具，可以把avi, divx, mpeg文件转换 <br />
<a href="http://www.skycn.com/soft/20289.html" target="_blank">www.skycn.com/soft/20289.html</a> <br />
<br />
<br />
17. Xilisoft Video Converter V2.1.58.0111b <br />
<br />
视频转换工具，可以在DVD、VCD、SVCD、MOV、RM、AVI、 <br />
<a href="http://www.skycn.com/soft/22751.html" target="_blank">www.skycn.com/soft/22751.html</a> <br />
<br />
<br />
18. AVI MPEG to VCD SVCD DVD V4.3 <br />
<br />
AVI MPEG to VCD SVCD DVD 转换是一款功能强大的国产视 <br />
<a href="http://www.skycn.com/soft/20187.html" target="_blank">www.skycn.com/soft/20187.html</a> <br />
<br />
<br />
19. AVOne - RM to AVI/DVD/VCD/SVCD/MPEG Converter 3.46 <br />
<br />
是一款视频转换工具，能将RM/RAM/RMVB文件转变为AVI,DVD,VCD,SVCD,MPEG1,MPEG2等视频 <br />
<a href="http://www.onlinedown.net/soft/23293.htm" target="_blank">www.onlinedown.net/soft/23293.htm</a> <br />
<br />
<br />
20. Allok MOV Converter 1.6.2 <br />
<br />
将MOV格式文件转换为AVI, MPEG, WMV, DVD, VCD, SVCD的工具 <br />
download.pchome.net/multimedia/video/20241.html <br />
<br />
<br />
21. 宽网多媒体MP3转换器 1.01 <br />
<br />
实现MPEG1、VCD转MP3；MPEG2（含PS、TS流）、DVD转MP3；AVI（含DIVXXDIV等MPEG4文件） <br />
<a href="http://www.onlinedown.net/soft/40750.htm" target="_blank">www.onlinedown.net/soft/40750.htm</a> <br />
<br />
<br />
22. Super DVD Creator V9.10 <br />
<br />
DVD/VCD/SVCD制作软件，可以将Avi/Divx影片转换刻录为 <br />
<a href="http://www.skycn.com/soft/13309.html" target="_blank">www.skycn.com/soft/13309.html</a> <br />
<br />
<br />
23. Cucusoft AVI to DVD VCD SVCD MPEG Converter Pro 7.07 <br />
<br />
CucusoftAVItoDVD/VCD/SVCD/MPEGConverterPro是一个功能强大的视频文件转换工具,程序 <br />
<a href="http://www.onlinedown.net/soft/17552.htm" target="_blank">www.onlinedown.net/soft/17552.htm</a> <br />
<br />
<br />
24. Rm To AVI VCD SVCD DVD MPEG Converter 3.2 <br />
<br />
RMtoAVIVCDSVCDDVDMPEGConverter是一款将RM或RAM文件转换成AVI、DVD、VCD、SVCD和MPEG <br />
<a href="http://www.onlinedown.net/soft/25880.htm" target="_blank">www.onlinedown.net/soft/25880.htm</a> <br />
<br />
<br />
25. DVD2AVI V1.86 汉化版 <br />
<br />
DVD2AVI 可以迅速的把 DVD 转成 AVI 文件。 <br />
<a href="http://www.skycn.com/soft/3107.html" target="_blank">www.skycn.com/soft/3107.html</a> <br />
<br />
<br />
26. DVD to VCD AVI DivX Converter V3.2.69 汉化补丁 <br />
<br />
DVD to VCD AVI DivX Converter 是一款 DVD 剪辑转换和 <br />
<a href="http://www.skycn.com/soft/19753.html" target="_blank">www.skycn.com/soft/19753.html</a> <br />
<br />
<br />
27. DVD2SVCD 1.2.2 Build 2 <br />
<br />
全自动DVD转SVCD工具，能把DVD、PVA(DVB抓取文件)和AVI文件转成SVCD <br />
download.pchome.net/multimedia/dvd/dvdripper/11145.html <br />
<br />
<br />
28. Super DVD Creator 8.5 <br />
<br />
可以将AVI、DIVX和MPEG转换生成VCD、SVCD和DVD的软件。 <br />
download.pchome.net/multimedia/video/15579.html <br />
<br />
<br />
29. DVD to VCD AVI DivX Converter V3.2.69 <br />
<br />
是一个DVD剪辑和备份工具。它可以将DVD拷贝以及转换成 <br />
<a href="http://www.skycn.com/soft/14498.html" target="_blank">www.skycn.com/soft/14498.html</a> <br />
<br />
<br />
30. DVDx 2.0 <br />
<br />
DVDx能让您用一个步骤把DVD转换成VCD2.0、SCVD1.0或AVI <br />
download.pchome.net/multimedia/dvd/dvdripper/11146.html <br />
<br />
<br />
31. All to AVI VCD SVCD DVD Converter V3.3 <br />
<br />
All to AVI VCD SVCD DVD Converter 是影片转档的工具 <br />
<a href="http://www.skycn.com/soft/15305.html" target="_blank">www.skycn.com/soft/15305.html</a> <br />
<br />
<br />
32. AVOne Gold - DVD/VCD/SVCD/MPEG/AVI/ASF/MP3 Converter V3.36 <br />
<br />
一个功能强大的视频文件转换器，主要的特点包括：AVI文 <br />
<a href="http://www.skycn.com/soft/16002.html" target="_blank">www.skycn.com/soft/16002.html</a> <br />
<br />
<br />
33. 龙腾紫雪(MediaFactory) V2.2.400 <br />
<br />
该软件可以把常见的VCD/DVD/MPG/MPEG/AVI/ASF文件转换 <br />
<a href="http://www.skycn.com/soft/15677.html" target="_blank">www.skycn.com/soft/15677.html</a> <br />
<br />
<br />
34. Ultra RM Converter 1.76 <br />
<br />
UltraRMConverter是一款可以帮助你将RM,RMVB分割、结合、转换成AVI,MPEG,VCD,SVCD,DVD <br />
<a href="http://www.onlinedown.net/soft/36587.htm" target="_blank">www.onlinedown.net/soft/36587.htm</a> <br />
<br />
<br />
35. AVI MPEG to VCD SVCD DVD 4.3 <br />
<br />
AVIMPEGtoVCDSVCDDVD转换是一款功能强大的国产视频文件格式转换工具。程序支持AVI/MPE <br />
<a href="http://www.onlinedown.net/soft/35209.htm" target="_blank">www.onlinedown.net/soft/35209.htm</a> <br />
<br />
<br />
36. MainConcept MPEG Encoder 1.42 汉化补丁 <br />
<br />
本软件是一个将AVI或QuickTime格式的文件转换为Mpeg文件的工具，是制作DVD、VCD和SVCD <br />
<a href="http://www.onlinedown.net/soft/37770.htm" target="_blank">www.onlinedown.net/soft/37770.htm</a> <br />
<br />
<br />
37. AVOne - AVI to DVD/VCD/SVCD/MPEG Converter 3.46 <br />
<br />
SuperAVItoDVD-VCD-SVCDconverter，一个功能强大的视频文件转换器，主要的特点包括：A <br />
<a href="http://www.onlinedown.net/soft/8339.htm" target="_blank">www.onlinedown.net/soft/8339.htm</a> <br />
<br />
<br />
38. WMV to AVI MPEG VCD SVCD DVD Converter 1.3.4 汉化版 <br />
<br />
WMVtoAVIMPEGVCDSVCDDVDConverter是一款功能强大的视频文件转换工具,程序可以将WMV视 <br />
<a href="http://www.onlinedown.net/soft/28809.htm" target="_blank">www.onlinedown.net/soft/28809.htm</a> <br />
<br />
<br />
39. Avi2Dvd V0.4.3 beta <br />
<br />
Avi2Dvd 是一款将avi/mkv/ogm转换为vcd/svcd/dvd的工具 <br />
<a href="http://www.skycn.com/soft/22951.html" target="_blank">www.skycn.com/soft/22951.html</a> <br />
<br />
<br />
40. AVI DivX to DVD SVCD VCD Converter V1.4.4 汉化版 <br />
<br />
一款强大的视频转换工具，能将AVI, DivX, MPEG1/2, WM <br />
<a href="http://www.skycn.com/soft/24021.html" target="_blank">www.skycn.com/soft/24021.html</a> <br />
<a href="http://www.soft8.net/soft8.php?page=2&amp;word=DVD" target="_blank">http://www.soft8.net/soft8.php?page=2&amp;word=DVD</a>转AVI&amp;site=all&amp;by=js&amp;num=280 <br />
<img src ="http://www.blogjava.net/conans/aggbug/210683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-25 21:40 <a href="http://www.blogjava.net/conans/articles/210683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DVD转成DVDRIP</title><link>http://www.blogjava.net/conans/articles/210681.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 25 Jun 2008 13:39:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210681.html</guid><description><![CDATA[先期准备工作 <br />
<br />
由于制作DVDrip的流程较为复杂，需要用到的工具软件也较多，因此事先应该做好准备工作，以免正式开工时手忙脚乱。 <br />
<br />
1、电脑硬件及工具软件的准备 <br />
<br />
制作DVDrip是一项对电脑配置要求较高的工作，你最好要拥有一颗强力的CPU，以下为建议配置： <br />
<br />
CPU——至少700MHz，越高越好。 <br />
<br />
硬盘——至少要有5GB左右的剩余空间。 <br />
<br />
内存——最低128MB，256MB以上尤佳。 <br />
<br />
光驱——8倍速以上DVD-ROM。 <br />
<br />
制作DVDrip需要的工具软件： <br />
<br />
文件拷贝软件——SmartRipper <br />
<br />
计算视频流码率软件——Advanced DivX Bitrate Calc！ <br />
<br />
视频部分制作软件——FlasK MPEG或Xmpeg <br />
<br />
音频分离及制作软件——DVD2AVI <br />
<br />
最终合成软件——NanDUB <br />
<br />
字幕制作软件——VobSub <br />
2、复制VOB文件至硬盘 <br />
<br />
从DVD盘片中复制.vob文件至硬盘，是最为关键的准备工作，复制质量的好坏将直接影响到最终输出的DVDrip效果。 <br />
<br />
打开DVD根目录，可以看到这里面有两个子目录：AUDIO_TS与VIDEO_TS。AUDIO_TS中没有任何内容，DVD的所有信息都存放在VIDEO_TS目录中。这个目录包含了.vob、.ifo和.bup等三种类型的文件。 <br />
<br />
其中VOB文件用来保存MPEG-2格式的影音数据，这些数据不仅包含影片本身内容，还包含了菜单和按钮等画面，以及多种字幕的子画面流。而IFO则用于控制VOB文件的播放。由于IFO文件关系到光盘能否正常播放，因此所有的IFO文件都有一个备份——即相应同名的BUP文件。要制作DVDrip，只要将记录正片数据的VOB文件和IFO文件复制到硬盘就可以了。 <br />
<br />
专门用于复制VOB文件的软件有很多，如CladDVD、DVD Decypter、DeCSS、Vstrip GUI等，笔者在这里推荐使用SmartRipper。它只有几百KB大，使用方便，非常适合新手。 <br />
<br />
将DVD盘片放入光驱，运行SmartRipper，自动弹出操作界面，在&#8220;Movie&#8221;界面的&#8220;Input&#8221;&#8594;&#8220;Chapters&#8221;中选择要复制的片段(如图1)，在Target处选择保存路径；点击&#8220;Stream Processing&#8221;标签选取音轨。 <br />
<br />
<br />
而后点击左方的&#8220;Files&#8221;按钮，勾选要复制的VOB文件。回到&#8220;Movie&#8221;界面，点击左下方的&#8220;Start&#8221;键，开始复制。 <br />
3、从VOB主文件中分离音频文件 <br />
<br />
由于DVDrip是合成压缩出的文件，因此DVDrip的视频和音频部分要分开制作，此时我们就要从VOB主文件中将音频文件分离出来。推荐使用软件DVD2AVI。它也可将DVD直接转为AVI文件，但效果不太理想，因此在此只用它来分离AC3音轨。 <br />
<br />
运行DVD2AVI，点击&#8220;文件&#8594;打开&#8221;，导入刚刚得到的Godfather.vob源文件。然后选择&#8220;音轨&#8221;，每个音轨上的语种都是不同的，因此要事先确认你所需的语种在哪个音轨上。例如所需的英语在音轨1上，就在&#8220;音轨编号&#8221;处选择&#8220;音轨1&#8221;，在&#8220;MPEG音频&#8221;处选择&#8220;分离混合的所有音轨&#8221;。 <br />
<br />
接着进入&#8220;视频&#8221;选项，在&#8220;视频&#8594;区域操作&#8221;处选&#8220;无&#8221;，而后在&#8220;色彩空间&#8221;处选&#8220;YUV 4∶2∶2&#8221;，其他都保持为默认设置。最后点击&#8220;文件&#8221;&#8594;&#8220;保存工程&#8221;即开始音轨分离，分离完毕后得到一个后缀名为.d2v的工程文件，同时得到分离出来的AC3文件。 <br />
<br />
此时有两种选择，一种是将AC3音轨转换为MP3音轨后再与视频部分整合成AVI文件；另一种是直接将AC3音频文件保留下来，与视频部分整合。为保留DVD特有的环绕立体音效，建议还是使用AC3音轨。文件虽然大了一些，但是绝对值得！ <br />
<br />
4、计算视频流的码率 <br />
<br />
要想让做好的DVDrip便利于网络间的传递交流，并且能够放进一两张刻录光盘中收藏，保持较小的个头非常重要。而DVDrip的大小则取决于影片的长度、视频流的码率、音频流的码率等因素。所谓码率，就是指每秒时间内的数据流量。码率越高，对画面的描述就越精细，就越接近于原始画面，但同时也需要更大的存贮空间。 <br />
<br />
<br />
图2计算出视频流的码率 <br />
<br />
笔者推荐使用Advanced DivX Bitrate Calc！来计算视频流的最佳码率。它个头虽小，功能却不弱，可根据影片的长度、视频及音频的格式结合CD的数量与容量，计算出视频流的最佳码率，或者算出DVDrip所要占用的硬盘空间。其设定十分简单，&#8220;Input Length Video&#8221;表示&#8220;输入影片长度&#8221;，&#8220;Input Sound Rate&#8221;表示&#8220;输入声音比率&#8221;，&#8220;Input HDD Space&#8221;表示选择CD盘数量，其中&#8220;Custom&#8221;为自定义容量。以上选项都妥当后，软件就会自动给出最精确的视频流码率了(如图2)。 <br />
<br />
视频部分制作 <br />
<br />
FlasK MPEG和Xmpeg是两个相当优秀的多媒体转换软件，不但能将MPEG-1和MPEG-2影音文件转换成其他常见的多媒体影音格式，还能够在已安装DivX解码器的电脑上快速制作AVI文件。实际上Xmpeg就是在FlasK MPEG的基础上改良而来的，它修正了FlasK MPEG的一些BUG，并增加了较多的功能，最新版已能支持中文操作界面。因此笔者推荐使用Xmpeg来制作DVDrip的视频部分。 <br />
<br />
运行Xmpeg，软件会自动要求选择语言环境，选&#8220;中文(简体)&#8221;后即进入操作主界面 <br />
<br />
点击&#8220;文件&#8594;打开文件&#8221;，导入事先拷贝好的Godfather.vob文件，导入时间可能会稍长，请耐心等候。由于许多影片至少有两个以上的音轨(DD2.0 / DD5.1)，导入成功后，会跳出一个提示窗口，要你先选择音轨，其中0x80表示杜比5.1音轨，选它即可。 <br />
<br />
选完后按右下角绿箭头，主界面将会显示影片的预览画面，同时带有一个名为&#8220;Video Player&#8221;的进度调谐器 <br />
<br />
接下来，我们就该对参数进行设置了。请选择&#8220;选项&#8221;&#8594;&#8220;输出格式选项&#8221;，此时会弹出名为&#8220;AVIPlugin&#8221;的设置面板，先设置&#8220;Audio Codec&#8221;(音频编码)部分，如想保留AC3音效，可设定为&#8220;DivX Audio&#8221;；下面的&#8220;Available formats for audio codec&#8221;(音频编码可用格式)相应设置为128kbit/s，48,000Hz，Stereo格式。 <br />
<br />
接着设置&#8220;Video Codec&#8221;部分，&#8220;Video Codec&#8221;部分可供选择的&#8220;Codec(编码)&#8221;很多，应根据你所使用的DivX解码器的类型进行选择，笔者使用的是DivX Codec 4.12，选定后会弹跳出Divx Video Codec设置窗口，由于DivX Codec 4.x版新增了&#8220;2-pass&#8221;功能，使得画质及动态效果更上一层楼，虽然要比&#8220;1-pass&#8221;多花上一倍的时间处理，但为了优异的效果，还是建议采用&#8220;2-pass&#8221;模式，请在这个画面选择&#8220;2-pass，first pass&#8221;。下面的数据速率设定，按照我们在准备工作时算好的视频流码率来决定。其余设定根据实际需求设定，完毕后按&#8220;OK&#8221;回到上一个画面，并按下右下角的绿色箭头回到主界面。 <br />
<br />
在主界面选择&#8220;选项&#8594;全局项目选项&#8221;，弹出&#8220;Option&#8221;窗口，对其他重要选项进行设定： <br />
<br />
视频标签：&#8220;画面帧尺寸&#8221;和&#8220;时间基准&#8221;通常无须改变，保持默认即可。&#8220;iDCT选项&#8221;关系到影片译码的速度，你可根据自身电脑CPU的速度按&#8220;Next&#8221;选择一种较快的模式。&#8220;视频构建&#8221;中的&#8220;重建优质图像&#8221;和&#8220;Deinterlace&#8221;(消除隔行扫描)应予勾选，这样可以改善画质、消除隔行扫描的DVD中出现的拉丝现象，从而更流畅地播放影片。 <br />
<br />
音频标签：音频设置较为简单。如果想保留AC3音效，请在&#8220;音频模式&#8221;中选择&#8220;直接数据流复制&#8221;；如果选择&#8220;音频解码&#8221;，那么在下面的&#8220;采样频率&#8221;中请勾选&#8220;同输入一致&#8221;，并选择48000Hz即可。 <br />
<br />
执行处理标签：经过笔者测试，该处的设置大多只需按默认值设定即可。只有&#8220;Aspect ratio&#8221;(画面比例设定)部分应根据影片本身所采用的银幕格式，如宽银幕、全银幕、欧式银幕等来设定最正确的比例。 <br />
<br />
文件标签：在此处设定输出文件的保存路径。 <br />
<br />
常规标签：&#8220;编码时间&#8221;是用来分割影片的，如不想分割的话，直接勾选&#8220;编码整个文件&#8221;即可。若想把影片分割成两部分，只要将框内的数字除以二就行了，不过有小数点的话要无条件进位。在之前设置Divx Video Codec时，如果我们采用了&#8220;2-pass&#8221;模式，那么&#8220;2nd Pass Enabled&#8221;这地方就要打勾。 <br />
<br />
以上一切设置就绪后，回到主界面窗口，进入&#8220;运行&#8221;选择&#8220;开始转换&#8221;，Xmpeg就会对VOB文件进行编码，并输出后缀名为.avi的MPEG-4视频文件。DVDrip的视频部分制作到此完工 <br />
音频部分制作 <br />
<br />
实际上，AC3音频部分的制作在以上介绍的用DVD2AVI软件单独提取，或是用Xmpeg压制视频的过程中就已完成。之所以将这部分独立出来，是因为DVDrip的音频部分分为AC3音频和MP3音频两种，有些朋友为了让做出来的DVDrip体积能小一点，而不采用AC3音频。MP3音频虽然可减小DVDrip的体积，但由AC3提供的5个全频域声道加1个超重低音声道组成的5.1音效也就此丧失，因此如非特别需要，笔者不推荐使用MP3音频进行最后的压缩合成。将AC3音频转换为MP3十分容易，大家可用Lame、Azid、Blaze Media Pro等软件自行转换，笔者在此不再赘述。 <br />
<br />
下面我们接着来看如何将制作好的视频和音频部分合并成一个AVI文件。 <br />
<br />
合成为AVI文件 <br />
<br />
NanDub是一款基于VirtualDUB开发的DivX编辑、制作软件，你的电脑只需安装有DivX 3.11或免费的Mpeg4v2两种解码器即可使用它。对于其他的DivX解码器，就只能使用NanDub附带的VirtualDub软件进行DVDrip的最终合成了。 <br />
<br />
笔者由于安装的是DivX 4.12解码器，因此就以VirtualDub汉化版作为AVI文件编辑的平台，进行最终的合成。使用NanDub大体上与此相同。 <br />
<br />
启动VirtualDub，首先选择&#8220;文件&#8221;&#8594;&#8220;打开视频文件&#8221;，导入用Xmpeg生成的无声的Godfather.avi文件，开始查看并编辑文件(如图5)。 <br />
<br />
<br />
图5用VirtualDub导入AVI文件 <br />
<br />
通过&#8220;文件&#8221;&#8594;&#8220;滤镜&#8221;打开滤镜面板，点击&#8220;添加&#8221;，在添加面板中选择添加&#8220;Resize&#8221;滤镜在此你可调整画面的大小。 <br />
<br />
<br />
<br />
<br />
调整至满意状态后，可以合并音频部分了，在&#8220;音频&#8221;中选择&#8220;直接复制音频流&#8221;，再在&#8220;视频&#8221;同样选择&#8220;直接复制音频流&#8221;，之后依次选择&#8220;音频&#8221;&#8594;&#8220;AC3音频&#8221;，导入先前用DVD2AVI或Xmpeg分离出来的AC3音轨文件；如要导入MP3音轨文件，则选择&#8220;音频&#8221;&#8594;&#8220;MP3音频&#8221;。 <br />
<br />
接着在&#8220;视频&#8221;&#8594;&#8220;SBC选项&#8221;中选择&#8220;位频率计算器&#8221;，弹出位频率计算器，在该窗口的&#8220;最终尺寸&#8221;处填入你要生成的AVI文件的大小及数量。例如输入700MB&#215;2，就表示最后要生成2个700M大小的AVI文件而后点击旁边的&#8220;计算&#8221;按钮，软件就会自动计算出合适的码流。 <br />
<br />
<br />
<br />
OK，终于到了最激动人心的时刻，请选择&#8220;文件&#8221;&#8594;&#8220;另存为AVI&#8221;，在弹出的窗口中选择保存路径并填入相关信息等内容，最后按&#8220;保存&#8221;，就会生成最终的音频-视频交错文件。AVI文件的合成至此大功告成。 <br />
<br />
现在，只要再加上外挂字幕，一部完整意义上的DVDrip就制成了。 <br />
外挂字幕制作 <br />
<br />
欣赏外语电影，字幕的重要性是不言而喻的。如果没有字幕而你的英文又欠佳的话，那看着精彩的外语大片可就是一件痛苦的事情了。因此字幕是构成DVDrip的重要组成部分。目前网络上提供下载的DVDrip字幕分为两大类，一类是基于图形格式的如.idx和.sub字幕；另一类是基于文本格式的如.srt、 <br />
<br />
.sub、.ssa、.smi等字幕。我们现在就以VobSub这款优秀的DVDrip字幕文件制作和辅助播放软件为平台，分别介绍这两种字幕的制作方法： <br />
<br />
1、图形字幕的制作 <br />
<br />
从VobSub的程序组中启动VobSub Configure命令，点击&#8220;Open&#8221;按钮(如图8)，在对话框中选择&#8220;文件类型&#8221;为&#8220;IFO and Vobs&#8221;，然后选择DVD中包含正片信息的IFO文件，并选择一个存放字幕文件的文件夹。 <br />
<br />
<br />
图8启动VobSub Configure <br />
<br />
接着进入字幕流选择画面(如图9)，选好字幕后确定即开始建立字幕索引。 <br />
<br />
<br />
图9字幕流选择 <br />
<br />
建立索引完成后，返回主窗口，选择自己喜欢的字幕颜色与位置，最后按&#8220;OK&#8221;就会在指定存放的目录中生成.idx和.sub两个文件，把它们的主文件名改为与.avi的主文件名相同后，同置于一个目录中，即可实现外挂播放了。 <br />
<br />
☆字幕切割与合并： <br />
<br />
由于一部影片可能会分割为多个AVI文件存放，因此字幕文件也要做相应的分割。在分割字幕前要先知道AVI文件的精确长度，我们可以用VirtualDub打开AVI文件，将进度条拖到最后，就可以看到影片的精确时长了。然后调用VobSub程序组中的&#8220;VobSub Cutter&#8221;(如图10)，点击&#8220;Open&#8221;选择待分割的字幕文件，在&#8220;Start&#8221;处输入开始时间，&#8220;End&#8221;处输入结束时间。再点击&#8220;Save as&#8221;即可将分割后的字幕文件保存下来。 <br />
<br />
<br />
图10调用VobSub Cutter分割字幕 <br />
<br />
同理，要合并字幕，可调用VobSub程序组中的&#8220;VobSub joiner&#8221;，在两个Input处导入要合并的字幕文件，在Output处设定输出文件的位置和文件名，在&#8220;Beginning of&#8221;处填入两段字幕交接处的时间码，最后点&#8220;GO&#8221;即完成合并。 <br />
<br />
☆去除字幕中的多余语言： <br />
<br />
用文本编辑器打开.idx文件，去掉不想要的字幕信息后保存。再使用VobSub程序组中的Subresync工具打开这个.idx文件，保存成新的字幕文件即可。 <br />
<br />
2、文本字幕的制作 <br />
<br />
所谓文本字幕，就是提取DVD中的字幕信息流，生成图像后再进行OCR识别而获得的一种字幕形式。它具有体积小巧、易于编辑、便于调整等优点。制作文本字幕我们要用到SubRip这个软件。 <br />
<br />
<br />
图11选择字幕流的语言种类 <br />
<br />
运行SubRip，点击&#8220;File&#8221;&#8594;&#8220;Open VOB&#8221;，弹出选择对话框。点击其中的&#8220;Open IFO&#8221;，打开DVD正片的.ifo文件，在Language Stream处选择字幕流的语言种类(如图11)，其余均保持默认选项，点击&#8220;Start&#8221;按钮，SubRip就会自动开始识别指定文件中的字幕流，当每个字母第一次出现时软件都会要求你进行字母验证，之后再出现同样的字母就会被自动识别。全文识别完毕后，SubRip还提供&#8220;Post OCR Correction&#8221;功能对文件进行校正。最后点击&#8220;File&#8221;&#8594;&#8220;Save as&#8221;将字幕保存为.srt格式的文件即完成了文本字幕的制作。 <br />
3、著名字幕网站推介： <br />
<br />
牛过字幕站：<a href="http://www.niuguo.com//" target="_blank">http://www.niuguo.com//</a> <br />
<br />
新视界字幕站：sn-<a href="http://www.com/dvd/film.asp" target="_blank">www.com/dvd/film.asp</a> <br />
<br />
至此，一部完整的DVDrip就新鲜出炉了。你可以把它刻录到光盘中，或通过网络与你的朋友们一起分享DVDrip所带来的视听震撼了！ <br />
<br />
DVD小知识 <br />
<br />
D5：DVD-5的简称，即单面单层，最大容量4.7GB，一面数据，另一面一般印刷文字或图案。 <br />
<br />
D9：DVD-9的简称，即单面双层，最大容量8.5GB，一面数据，另一面一般印刷文字或图案。 <br />
<br />
D10：DVD-10的简称，即双面单层，最大容量9.7GB，两面都是数据面。 <br />
<br />
D14：DVD-14的简称。即双面多层，最大容量13GB。以两面三层形式记录数据，第一面为双层，第二面单层。 <br />
<br />
D18：DVD-18的简称，即双面双层，最大容量17GB，两面都是数据面。 <br />
<br />
有损压缩：简称YSYS，意思是将经过解密的原汁原味的数码信号进行压缩，以便装入容量较小的盘面里。有损压缩所产生出来的DVD盘片，无论图像还是声音质量都会有所下降。 <br />
<br />
一、什么是 RMVB <br />
RMVB 中的 VB，指的是 VBR，即 Variable Bit Rate 的缩写，中文含义是可变比特率。 <br />
RMVB 打破了压缩的平均比特率，使在静态画面下的比特率降低，来达到优化整个影片中比特率，提高效率，节约资源的目的，一般来说，一个700MB的 DVDrip 采用平均比特率为450Kbps的压缩率，生成的 RMVB 大小仅为400MB，但是画质并没有太大变化。可种技术，早在MP3中就得以应用，现在随着 Real 公司的 Helix Producer 9 的推出，也应用到了视频领域。 <br />
<br />
二、如何制作 RMVB <br />
1、制作之前的准备 <br />
由于 RMVB 是最新的编码方式，所以现在只有使用 Real 公司的 Helix Producer 9，才可以制作 RMVB 格式的视频文件。Helix Producer 9 分为 Basic 版和 Plus 版，Plus 版的功能比 Basic 版要更为强大，但是 Basic 版是免费的，可以在http:/<a href="http://www.real.com/" target="_blank">www.real.com</a>下载到。 <br />
<br />
2、制作 RMVB <br />
如果我们把700MB的 DVDrip 文件转成平均比特率为450Kbps的 RMVB 文件，大概需要4-10小时（依CPU性能决定），在制作过程中，电脑不能干其他事情，制作必须一气呵成，如果中途停止，那么只有重新来过了。 <br />
* 导入文件。运行主程序（图一），点击 Browse 选择待转换的 DVDrip 文件。如果你的电脑可以正常播放 DVDrip 电影并且字幕正常，那么 Helix Producer 会自动将字幕转入 RMVB 文件。 <br />
* 转换细节设置。点击 Audiences 调整压缩参数，在 Helix Producer 中，已经为用户提供了很多内置的参数模板（图二），要制作 RMVB 文件，必须把设置对话框右边以有的的模板删除，因为 RMVB 不支持多速率。然后在左边的模板窗口选择适当的 VBR 模板，这里我们使用 S-450K Surround VBR Download 模板，双击这个模板，我们可以看到该模板的更为详细的设置，其中里面最高比特率为900Kbps，这已经足够满足现在所有清晰影片的要求了。下面我们对模板进行细微调整（这个功能只有 Plus 版具备）。 <br />
在图三中，平均比特率决定了静态画面的清晰度，对最后生成的文件大小起决定作用；而最大比特率决定了动态画面的品质，避免了马赛克的产生。如果你的影片是动作影片的话，那么你需要把最大比特率设置到1500Kbps以上，这样才会得到更好的效果。 <br />
另外在图三中的 Target frame rate 处，可以对影片的FPS进行调整，FPS调整并不影响影片的清晰度，但是会影响影片的流畅程度，同时也对生成文件大小起作用。默认设置为30FPS，如果生成文件过大，你也可以设置成24FPS，因为人眼几乎无法分辨24FPS和30FPS的差别，设置完成之后，点击 Ok ，回到图二的界面中。 <br />
* 设置视频过滤器和版权信息。设置视频过滤器可以通过点击 Video Filters 来调整，视频过滤器用于调整影片画面的一些设置，推荐选上 Black Level Correction 选项，他可以提高影片的亮度和对比度，其他设置使用默认值即可。在 Clip Information 里面可以设置影片的版权信息（大片出自你手）。 <br />
* 开始生成 RMVB 文件。双击图一右下表中的文件项，你可以改变文件的存储位置。然后按下红色的 Encode 按钮，压缩就开始了。</ca>
<img src ="http://www.blogjava.net/conans/aggbug/210681.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-25 21:39 <a href="http://www.blogjava.net/conans/articles/210681.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 用 Firebug 动态调试和优化应用程序</title><link>http://www.blogjava.net/conans/articles/209619.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Fri, 20 Jun 2008 15:26:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/209619.html</guid><description><![CDATA[<p><a name="N10053"><span class="atitle">简介</span></a></p>
<p>Firebug 是 Mozilla Firefox 浏览器的开源扩展，提供了很多工具，可以监视、编辑和调试任何 Web 站点的级联样式表（CSS）、HTML、文档对象模型（DOM）和 JavaScript。Firebug 包括一个 JavaScript 控制台、一个日志记录 API 以及一种有用的网络监视器。借助 Firebug，可以很轻松地调试和优化 Web 和 Ajax 应用程序。</p>
<p>本文将帮助您熟悉所如下的 Firebug 特性： </p>
<ul>
    <li>编辑活动 Web 页面的 HTML、CSS 和 JavaScript
    <li>调试和剖析报告
    <li>进行日志记录以测试执行时间
    <li>使用 Network Monitor 分析 Web 页面的加载时间
    <li>错误报告 </li>
</ul>
<p>&nbsp;</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10077"><span class="atitle">立即开始</span></a></p>
<p>使用 Firefox，<a href="http://www.getfirebug.com/" cmimpressionsent="1"><font color="#5c81a7">下载 Firebug</font></a>。通过单击页面右侧的橙色按钮 <strong>Install Firebug</strong> 安装此扩展。 </p>
<p>Firefox 安装了此扩展后，重启浏览器。要使用 Firebug： </p>
<ol>
    <li>转到任何一个 Web 页面并按 <strong>F12</strong> 在浏览器窗口打开 Firebug。
    <li>按 <strong>CTRL-F12</strong> 在另一个窗口打开 Firebug（如果有两个监视器，这是一个很好的特性）。
    <p>本文使用了第一种方法在相同的浏览器窗口中打开 Firebug，如图 1 所示：</p>
    </li>
</ol>
<p>&nbsp;</p>
<br />
<a name="fig1"><strong>图 1. 安装后的 Firebug</strong></a><br />
<img height="608" alt="安装后的 Firebug" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug1.jpg" width="543" /> <br />
<p>安装后，Firebug 是禁用的。单击 <strong>Enable Firebug</strong> 启用它，如图 2 所示：</p>
<br />
<a name="fig2"><strong>图 2. Firebug 显示了 developerWorks 的首页</strong></a><br />
<img height="769" alt="Firebug 显示了 developerWorks 的首页" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug2.jpg" width="572" /> <br />
<p>本文的后面的内容将讨论 Firebug 的特性。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N100CF"><span class="atitle">HTML 和 CSS 工具</span></a></p>
<p>HTML 和 CSS 工具包括：HTML 检查和编辑、CSS 编辑和 CSS 可视化。 </p>
<p><a name="N100D8"><span class="smalltitle"><strong><font size="3">检查和编辑 HTML</font></strong></span></a></p>
<p>可以使用 HTML 检查特性在源代码中定位可视 HTML。</p>
<ol>
    <li>在 Firebug 窗口，单击 <strong>Inspect</strong>。
    <li>将鼠标移到任何一个 HTML 组件之上。这样就可以在 Firebug 窗口上看到该 HTML 元素（被蓝色方框围绕）和 HTML 源代码。如图 3 的示例： <br />
    <br />
    <a name="fig3"><strong>图 3. 在 Firebug 检查 HTML</strong></a><br />
    <img height="773" alt="在 Firebug 检查 HTML" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug3.jpg" width="567" /> <br />
    <br />
    <li>单击选中的 HTML 元素。有趣的是这会使此次检查&#8220;锁定&#8221;到所选定的元素。
    <li>可以转到 Firebug 窗口并单击 <strong>Edit</strong> 编辑选定的元素。
    <p>图 4 给出了 Firebug 编辑窗口以及浏览器窗口中已编辑的文本。&#8220;Editing with Firebug&#8221; 已经代替了原先的 Ajax 标题。</p>
    <br />
    <br />
    <a name="fig4"><strong>图 4. 编辑 HTML</strong></a><br />
    <img height="771" alt="编辑 HTML" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug4.jpg" width="568" /> <br />
    <br />
    </li>
</ol>
<p>在检查元素时，将会看到 Firebug 窗口内的元素嵌套，如图 5 所示：</p>
<br />
<a name="fig5"><strong>图 5. 元素嵌套</strong></a><br />
<img height="30" alt="元素嵌套" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug5.jpg" width="351" /> <br />
<p><a name="N10129"><span class="smalltitle"><strong><font size="3">编辑 CSS</font></strong></span></a></p>
<p>还可以通过检查这个 Web 页面进行 CSS 编辑。Inspection 视图会显示相关的 CSS 条目，包括继承样式。如图 6 的示例： </p>
<br />
<a name="fig6"><strong>图 6. CSS 检查</strong></a><br />
<img height="291" alt="CSS 检查" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug6.jpg" width="566" /> <br />
<p>CSS 工具还可用来编辑 CSS 即时属性、禁用属性、自动完成和图片预览，如图 7 所示： </p>
<br />
<a name="fig7"><strong>图 7. CSS 图片预览</strong></a><br />
<img height="290" alt="CSS 图片预览" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug7.jpg" width="567" /> <br />
<p><a name="N10153"><span class="smalltitle"><strong><font size="3">CSS 的可视化</font></strong></span></a></p>
<p>CSS 的可视化在检查 HTML（回顾 <a href="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/#fig3" cmimpressionsent="1"><font color="#996699">图 3</font></a> 中的蓝色边框）已经展示过了。Firebug Layout 选项卡显示了更多的信息，比如间隙、 偏移和其他相关的量度。图 8 中的布局窗口则显示了一个导航元素的量度： </p>
<br />
<a name="fig8"><strong>图 8. CSS 盒的量度</strong></a><br />
<img height="758" alt="CSS 盒的量度" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug8.jpg" width="567" /> <br />
<p>图 9 展示了能即时编辑 CSS 盒的奇妙的 Firebug 特性： </p>
<br />
<a name="fig9"><strong>图 9. CSS 盒编辑</strong></a><br />
<img height="758" alt="CSS 盒编辑" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug9.jpg" width="565" /> <br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10181"><span class="atitle">JavaScript 工具</span></a></p>
<p>现在，JavaScript 工具是 Web 开发中最有用的工具之一。Firebug 提供了调试、剖析、日志记录和命令行控制台特性。 </p>
<p><a name="N1018A"><span class="smalltitle"><strong><font size="3">调试和剖析</font></strong></span></a></p>
<p>Firebug JavaScript 工具包括断点、监视表达式和典型调试器中常见的其他一些工具。图 10 展示了断点和逐步调试的实际例子。请注意作为工具提示的主机变量的值。</p>
<br />
<a name="fig10"><strong>图 10. JavaScript 调试器</strong></a><br />
<img height="810" alt="JavaScript 调试器" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug10.jpg" width="566" /> <br />
<p>有用的调试工具能： </p>
<ul>
    <li>直接导航到 JavaScript 中的特定行
    <li>监视表达式（可以是任意的 JavaScript 表达式）
    <li>以可视格式调用堆栈
    <li>条件断点
    <li>错误后进行调试的能力 </li>
</ul>
<p>&nbsp;</p>
<p>JavaScript 剖析非常有用。如 Firebug 中的其他特性一样，剖析也很容易使用。单击 Console 选项卡上的 <strong>Profile</strong> 启动剖析器，如图 11 所示： </p>
<br />
<a name="fig11"><strong>图 11. 启动 JavaScript 剖析器</strong></a><br />
<img height="109" alt="JavaScript 剖析器" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug11.jpg" width="567" /> <br />
<p>剖析开始后，可以浏览一下此站点。单击 <strong>Profile</strong> 获得剖析报告，如图 12 所示： </p>
<br />
<a name="fig12"><strong>图 12. JavaScript 剖析器报告</strong></a><br />
<img height="812" alt="JavaScript 剖析器报告" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug12.jpg" width="565" /> <br />
<p>该报告显示了花在函数上的时间和平均时间等等。 </p>
<p><a name="N101E4"><span class="smalltitle"><strong><font size="3">JavaScript 日志记录 </font></strong></span></a></p>
<p>对于更愿意使用老的日志记录（而非调试）方式的开发人员，Firebug 提供了日志记录功能。日志记录使用的是一种 Firebug JavaScript API。最简单的一种日志条目是 <code>console.log("logging");</code>。</p>
<p>Console API 包含其他一些功能，如清单 1 所示： </p>
<br />
<a name="listing1"><strong>清单 1. Firebug Console API 示例</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">
            console.time("test timer");
            console.log("Hello from ",document.title);
            console.info("This is info");
            console.warn("This is warning");
            console.error("This is error");
            console.timeEnd("test timer");
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>可以使用 <code>console.time</code> 和 <code>console.timeEnd</code> 来测量执行时间。在详细报告中显示结果的 <code>console.profile()</code> 和 <code>console.profileEnd()</code> （见清单 1）也可用来测量执行时间。</p>
<p>图 13 显示了这些结果。JavaScript 控制台日志测试功能被添加到由 Web 服务器提供服务的页面中。</p>
<br />
<a name="fig13"><strong>图 13. Console 日志</strong></a><br />
<img height="524" alt="Console 日志" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug13.jpg" width="567" /> <br />
<p>Console API 内其他有用的特性还有堆栈跟踪、对象检查和字符串格式化。 </p>
<p><a name="N10226"><span class="smalltitle"><strong><font size="3">JavaScript 命令行</font></strong></span></a></p>
<p>Firebug 最为强大特性之一就是 JavaScript 命令行。这种命令行的使用方式与其他命令行一样；它执行您编写的所有 JavaScript 代码，好像它们就是页面的一部分一样。通过命令行，可以检查 DOM、获得属性等等。所有返回值都显示在控制台上。</p>
<p>命令行具有自动完成功能（使用 Tab 键）以及完善的文本编辑器（能够编写完整的函数而不仅仅是几行代码）等等。图 14 给出了一个简单的控制台会话。请注意 Web 页面左上角的徽标。这里也可以进行即时编辑。</p>
<br />
<a name="fig14"><strong>图 14. 命令行 JavaScript</strong></a><br />
<img height="812" alt="命令行 JavaScript" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug14.jpg" width="569" /> <br />
<p>与控制台类似，命令行也有一个 API，它包含可用于 Firebug 的特殊函数，比如 <em>$(id)</em>。该函数能够返回带有给定 id 的元素。 </p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10247"><span class="atitle">网络监控</span></a></p>
<p>Firebug Network Monitor 特性可用来监视加载 Web 页面所花费的时间。使用 Net 选项卡可以看到进度栏，该进度栏显示了一个文件相对所有其他文件开始和停止加载的时间。Network Monitor 分开每个文件的流量，因此就可以查看加载图像、JavaScript、HTML 等各占用了多少时间。此外，还可以查看资源是否从浏览器缓存中加载。</p>
<p>对于本例中的 Ajax 开发，Firebug 在 Net 选项卡和 Console 选项卡中均显示了每个 XMLHttpRequest。 </p>
<p>图 15 显示了如何利用 Network Monitor 查看 HTTP 请求和响应头。要查看 HTTP 头，只需单击每个请求左侧的箭头将其展开。全部请求、已用时间和内容的大小均显示在 Firebug 窗口底部。</p>
<br />
<a name="fig15"><strong>图 15. Network Monitor</strong></a><br />
<img height="836" alt="Network Monitor" src="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/firebug15.jpg" width="566" /> <br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10265"><span class="atitle">其他特性</span></a></p>
<p>Firebug 的其他特性包括：</p>
<p><a name="N1026E"><span class="smalltitle"><strong><font size="3">错误报告</font></strong></span></a></p>
<p>一旦错误发生，Firebug 能够提供有用的：</p>
<ul>
    <li>状态栏指示器
    <li>行号、文件和堆栈跟踪
    <li>调试器集成
    <li>搜索和过滤器 </li>
</ul>
<p>Firebug 还会显示只与所查看的页面相关的错误。</p>
<p><a name="N10289"><span class="smalltitle"><strong><font size="3">DOM</font></strong></span></a></p>
<p>Document Object Model 是 Web 页面中的对象和函数的等级结构。Firebug DOM 包括所有定制的和标准的对象，而且 DOM explorer 能够分辨它们。这里同样可以进行 JavaScript 代码导航、自动完成和即时编辑。</p>
<p><a name="N10292"><span class="smalltitle"><strong><font size="3">定制</font></strong></span></a></p>
<p>Firebug 定制特性包括黑名单和白名单以及依据个人需要更改字体大小的功能。</p>
<img src ="http://www.blogjava.net/conans/aggbug/209619.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-20 23:26 <a href="http://www.blogjava.net/conans/articles/209619.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 收发网易,雅虎,hotmail,gmail邮件可能遇到的问题的解答</title><link>http://www.blogjava.net/conans/articles/209595.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Fri, 20 Jun 2008 15:07:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/209595.html</guid><description><![CDATA[<font color="#0000ff">一、我使用新申请的网易的126/163邮件箱，能在网页上收邮件，但是通过FOXMAIL无法收信，错误提示：没有权限使用POP3 ，但是我以前的126/163邮箱是可以正常使用的， 错误如下图提示，</font><a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg1.qq.com/2007/05/15/000/412.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg1.qq.com/2007/05/15/000/412.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
<br />
<font color="#0000ff">二、我使用新申请的网易的126/163邮件箱，能在网页上发邮件，但是通过FOXMAIL无法发信，错误提示： 550 用户被锁定。但是我以前的126/163邮箱是可以正常使用的， 如下图提示：</font><a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/428.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/428.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
<br />
答：对于这两类问题，常见于网易的126和163免费邮箱， 原因与解决办法如下： <br />
1）对于@126.com <br />
&nbsp;&nbsp; 126对免费用户不支持pop3和smtp，只对使用了126增值服务的用户提供使用POP客户端软件收取邮件的功能，因此如果您是新申请的126邮箱，您将不能使用客户端软件来收发邮件， 除非您购买了126的增值服务。<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg1.qq.com/2007/05/15/000/505.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg1.qq.com/2007/05/15/000/505.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
来源请参考网易客户帮助： <br />
http://www.126.com/help/client_04.htm <br />
2）对于@ 163.com <br />
&nbsp;&nbsp; 如果您是新注册的免费邮箱用户，在没有升级为3G邮箱空间后是无法使用pop3邮件客户端软件的，建议您在进入邮箱后，根据提示手动操作免费升级为3G邮箱后，再进行相关的客户端软件设置来收发邮件和管理您的免费邮箱。 <br />
&nbsp;&nbsp; 您可以在126邮箱免费升级（http://uinfo.mail.163.com/enlarge3g/index.htm）的页面，根据提示免费将邮箱升级为3G。 <br />
&nbsp;&nbsp; 注意：一些用户没有看清楚FOXMAIL的提示， 只看到FOXMAIL询问是否要重新输入密码， 但是没有看到上面的错误提示，因此反复输入密码，但是反复不通过。此类问题也可以参照上面的方式来解决。 <br />
<br />
<font color="#0000ff">三、我用FOXMAIL无法收取/发送 yahoo的邮件，错误情况如下：</font> <br />
&nbsp;&nbsp; 1）能收信, 但是发信出去后对方接收不到； <br />
&nbsp;&nbsp; 2）在收/发信时候进度窗口一直停住直到超时； <br />
&nbsp;&nbsp; 3）发信时还可能提示： <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/429.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/429.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
答 ： <br />
1) 对于雅虎中国(@yahoo.com.cn) <br />
<strong>首先在网页上要设置：</strong> <br />
&nbsp;如果你使用的是yahoo的测试版，首先要换回原来的邮箱。 <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/431.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/431.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;选择&#8220;邮件选项&#8221;，然后点击&#8220;账户信息&#8221; <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/432.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/432.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;编辑用户信息 <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/513.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/513.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
选择&#8221;Send to my Yahoo!Mail&#8221;<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg1.qq.com/2007/05/15/000/429.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg1.qq.com/2007/05/15/000/429.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
<br />
<strong>在FOXMAIL中配置如下</strong>(来源: http://help.cn.yahoo.com/answerpage.html?id=861 ) <br />
请您按照下面步骤，在Foxmail上添加一个雅虎邮箱帐户。 <br />
&nbsp;&nbsp;&nbsp; 1、请您首先查看是否已经订制了雅虎邮箱POP3+来信提醒； <br />
&nbsp;&nbsp;&nbsp; 2、如果您已经订制，则请您打开foxmail并点击工具栏中的&#8220;邮箱&#8221;，选择&#8220;新建邮箱帐户&#8221;； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/434.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/434.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;&nbsp;&nbsp; 3、随后请按照下图所示填写邮箱名称及密码，然后点击下一步； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/435.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/435.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;&nbsp;&nbsp; 4、随后点击完成； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/436.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/436.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;&nbsp;&nbsp; 5、然后点击工具栏中的&#8220;邮箱&#8221;—&#8220;修改邮箱帐户属性&#8221;； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg1.qq.com/2007/05/15/000/414.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg1.qq.com/2007/05/15/000/414.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;&nbsp;&nbsp; 6、如下图所示填写您的姓名和电子邮件地址，并点击确定； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/470.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/470.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;&nbsp;&nbsp; 7、然后选择&#8220;邮件服务器&#8221;并填写SMTP和POP3服务器的地址； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/473.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/473.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
<font color="#ff0000">注意: 经过FOXMAIL组测试, 目前 填写smtp服务器时,不要填写.cn后缀</font> <br />
&nbsp;&nbsp;&nbsp; 8、然后点击&#8220;高级&#8221;并勾选&#8220;此服务器要求安全连接（SSL）&#8221;，同时修改端口为&#8220;465&#8221;和&#8220;995&#8221;； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg1.qq.com/2007/05/15/000/478.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg1.qq.com/2007/05/15/000/478.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
&nbsp;&nbsp;&nbsp; 9、设置完之后，点击&#8220;确定&#8221;即可成功收发； <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/474.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/474.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
即可对雅虎中国邮箱进行收发邮件。 <br />
<br />
<font color="#ff0000">注意： <br />
&nbsp;&nbsp; 1、&#8220;POP3邮箱帐号&#8221;， 只能填写帐号名，不要在后面填写@yahoo.com.cn； <br />
&nbsp;&nbsp; 2、不要选择&#8221;自动启动Foxmail-Hotmail Proxy&#8221;项。</font> <br />
<br />
2) 对于@yahoo.com <br />
&nbsp;&nbsp; 原因：Yahoo.com邮件服务不再对免费用户开放，而只对使用了Yahoo! Mail Plus service的用户开放。 请参考yahoo官方说明： <br />
&nbsp; http://help.yahoo.com/l/us/yahoo/mail/original/mailplus/pop/pop-35.html <br />
&nbsp; 如果您已经在使用Yahoo!Mail Plus service，您可以按如下方式设置FOXMAIL：<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/476.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/476.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
<br />
<font color="#0000ff">四、我用FOXMAIL无法连接到 @hotmail.com收发邮件了，但是我周围有些朋友又能够收发hotmail。 如果是服务器有限制，但是为什么目前有一些第三方软件又号称能收发hotmail邮件呢?是不是FOXMAIL不支持hotmail呢？连接到hotmail时出现下图提示：</font> <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/477.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/477.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
答 ： <br />
&nbsp; Hotmail.com的邮件服务已经不再对用户免费开放了. 除了个别活跃老用户仍然可以继续使用外,其他用户,包括新用户(2004年以后注册的)必须到http://join.msn.com/general/email 去购买服务. <br />
&nbsp; 目前一些其他的共享软件使用一些第三方的免费服务器或者模拟了网页的提交方式来收取hotmail邮件. 但是这些方式都不稳定, 因此如果想正常使用hotmail, 建议直接购买邮件服务. <br />
<br />
<font color="#0000ff">五、我申请了gmail,能够登录网页进行邮件收发,但是无法使用FOXMAIL来对@gmail.com的POP收邮件. <br />
出现下图提示:</font> <br />
<a href="http://bbs.qq.com/allphoto.shtml?url=http://bbsimg.qq.com/2007/05/15/000/479.jpg" target="_blank"><img alt="网友贴图" hspace="5" src="http://bbsimg.qq.com/2007/05/15/000/479.jpg" onload="javascript:if(this.width />620)this.style.width=620" vspace=5 border=0></a> <br />
答：按官方设置,在webmail的option里选择支持pop即可收信 <br />
<br />
<br />
<br />
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2007-5-14 FOXMAIL开发组整理)&nbsp;&nbsp;
<img src ="http://www.blogjava.net/conans/aggbug/209595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-20 23:07 <a href="http://www.blogjava.net/conans/articles/209595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT) - 整理</title><link>http://www.blogjava.net/conans/articles/209589.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Fri, 20 Jun 2008 15:03:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/209589.html</guid><description><![CDATA[<p>当Adobe、Microsoft、Sun等一系列巨头开始表现出对"开源"的青睐时，"开源"的时代即将到来！</p>
<p>出处：<a href="http://www.sinoprise.com/read.php?tid-662-page-e-fpage-1.html">http://www.sinoprise.com/read.php?tid-662-page-e-fpage-1.html</a>，我没有改动原文，只是进行了一些排版和整理。<br />
参考文献：<a href="http://www.fsf.org/licensing/licenses/">http://www.fsf.org/licensing/licenses/</a></p>
<p>现今存在的开源协议很多，而经过Open Source Initiative组织通过批准的开源协议目前有58种（<a href="http://www.opensource.org/licenses/alphabetical">http://www.opensource.org/licenses/alphabetical</a>）。我们在常见的开源协议如BSD, GPL, LGPL,MIT等都是OSI批准的协议。如果要开源自己的代码，最好也是选择这些被批准的开源协议。</p>
<p>这里我们来看四种最常用的开源协议及它们的适用范围，供那些准备开源或者使用开源产品的开发人员/厂家参考。</p>
<p><strong>BSD开源协议（</strong><a href="http://www.fsf.org/licensing/licenses/index_html#OriginalBSD"><em>original</em> BSD license</a><strong>、</strong><span class="link-external"><a id="FreeBSD" href="http://www.freebsd.org/copyright/freebsd-license.html" name="FreeBSD">FreeBSD license</a></span><strong>、</strong><span class="link-external"><a id="OriginalBSD" href="http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6" name="OriginalBSD">Original BSD license</a></span><strong>）</strong></p>
<p>BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以"为所欲为",可以自由的使用，修改源代码，也可以将修改后的代码作为开源或者专有软件再发布。</p>
<p>但"为所欲为"的前提当你发布使用了BSD协议的代码，或则以BSD协议代码为基础做二次开发自己的产品时，需要满足三个条件：</p>
<ol>
    <li>如果再发布的产品中包含源代码，则在源代码中必须带有原来代码中的BSD协议。
    <li>如果再发布的只是二进制类库/软件，则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。
    <li>不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。 </li>
</ol>
<p>BSD 代码鼓励代码共享，但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码，也允许使用或在BSD代码上开发商业软件发布和销售，因此是对商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议，因为可以完全控制这些第三方的代码，在必要的时候可以修改或者二次开发。</p>
<p><strong>Apache Licence 2.0（</strong><span class="link-external"><a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>、<span class="link-external"><a href="http://www.apache.org/LICENSE-1.1">Apache License, Version 1.1</a>、<span class="link-external"><a href="http://www.apache.org/LICENSE-1.0">Apache License, Version 1.0</a></span></span></span><strong>）</strong></p>
<p>Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似，同样鼓励代码共享和尊重原作者的著作权，同样允许代码修改，再发布（作为开源或商业软件）。需要满足的条件也和BSD类似：</p>
<ol>
    <li>需要给代码的用户一份Apache Licence
    <li>如果你修改了代码，需要再被修改的文件中说明。
    <li>在延伸的代码中（修改和有源代码衍生的代码中）需要带有原来代码中的协议，商标，专利声明和其他原来作者规定需要包含的说明。
    <li>如果再发布的产品中包含一个Notice文件，则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可，但不可以表现为对Apache Licence构成更改。 </li>
</ol>
<p>Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。</p>
<p><strong>GPL（</strong><a id="GNUGPL" href="http://www.fsf.org/licensing/licenses/gpl.html" name="GNUGPL">GNU General Public License</a><strong>）</strong></p>
<p>我们很熟悉的Linux就是采用了GPL。GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用，但不允许修改后和衍生的代码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种linux，包括商业公司的linux和linux上各种各样的由个人，组织，以及商业软件公司开发的免费软件了。</p>
<p>GPL协议的主要内容是只要在一个软件中使用("使用"指类库引用，修改后的代码或者衍生代码)GPL 协议的产品，则该软件产品必须也采用GPL协议，既必须也是开源和免费。这就是所谓的"传染性"。GPL协议的产品作为一个单独的产品使用没有任何问题，还可以享受免费的优势。</p>
<p>由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议，对于使用GPL协议的开源代码，商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。</p>
<p>其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。</p>
<p><strong>LGPL（</strong><a id="LGPL" href="http://www.fsf.org/licensing/licenses/lgpl.html" name="LGPL">GNU Lesser General Public License</a><strong>）</strong></p>
<p>LGPL是GPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并发布和销售。</p>
<p>但是如果修改LGPL协议的代码或者衍生，则所有修改的代码，涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用，但不适合希望以LGPL协议代码为基础，通过修改和衍生的方式做二次开发的商业软件采用。</p>
<p>GPL/LGPL都保障原作者的知识产权，避免有人利用开源代码复制并开发类似的产品</p>
<p><strong>MIT（<a href="http://www.opensource.org/licenses/mit-license.php">MIT</a>）</strong></p>
<p>MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制.也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的.</p>
<script type="text/javascript" charset="utf8">cT="0";nc="#444444";nBgc="";nBorder="#F5E5A9";tc="#649B00";tBgc="#FFF4D0";tBorder="#F5E5A9";tDigg="%E6%8E%A8%E8%8D%90";tDugg="%E5%B7%B2%E8%8D%90";defaultItemUrl="WEB_URL";defaultFeedUrl ="http://feed.awflasher.com";</script><script src="http://re.xianguo.com/api/diggthis.js" type="text/javascript" charset="utf8"></script>
<img src ="http://www.blogjava.net/conans/aggbug/209589.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-20 23:03 <a href="http://www.blogjava.net/conans/articles/209589.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达式之道</title><link>http://www.blogjava.net/conans/articles/209563.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Fri, 20 Jun 2008 14:46:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/209563.html</guid><description><![CDATA[<font style="font-size: 14px" _extended="true">什么是正则表达式</font><font style="font-size: 14px" _extended="true">一个正则表达式，就是用某种模式去匹配一类字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用——很不幸，这篇文章也不能够改变这一点，不过，经过一点点练习之后我就开始觉得这些复杂的表达式其实写起来还是相当简单的，而且，一旦你弄懂它们，你就能把数小时辛苦而且易错的文本处理工作压缩在几分钟（甚至几秒钟）内完成。正则表达式被各种文本编辑软件、类库（例如Rogue Wave的tools.h++）、脚本工具（像awk/grep/sed）广泛的支持，而且像Microsoft的Visual C++这种交互式IDE也开始支持它了。</font>
<p _extended="true"><font style="font-size: 14px" _extended="true">我们将在如下的章节中利用一些例子来解释正则表达式的用法，绝大部分的例子是基于<tt _extended="true">vi</tt>中的文本替换命令和<tt _extended="true">grep</tt>文件搜索命令来书写的，不过它们都是比较典型的例子，其中的概念可以在sed、awk、perl和其他支持正则表达式的编程语言中使用。你可以看看</font><a href="http://net.pku.edu.cn/~yhf/tao_regexps_zh.html#Regular_Expressions_In_Various_Tools" _extended="true"><font style="font-size: 14px" color="#000000" _extended="true">不同工具中的正则表达式</font></a><font style="font-size: 14px" _extended="true">这一节，其中有一些在别的工具中使用正则表达式的例子。还有一个关于vi中文本替换命令（s）的</font><a href="http://net.pku.edu.cn/~yhf/tao_regexps_zh.html#ViSubstitutionCommandSyntax" _extended="true"><font style="font-size: 14px" color="#000000" _extended="true">简单说明</font></a><font style="font-size: 14px" _extended="true">附在文后供参考。</font></p>
<h2 _extended="true"><font style="font-size: 14px" _extended="true">正则表达式基础</font></h2>
<font style="font-size: 14px" _extended="true">正则表达式由一些普通字符和一些<em _extended="true">元字符（metacharacters）</em>组成。普通字符包括大小写的字母和数字，而元字符则具有特殊的含义，我们下面会给予解释。</font>
<p _extended="true"><font style="font-size: 14px" _extended="true">在最简单的情况下，一个正则表达式看上去就是一个普通的查找串。例如，正则表达式"testing"中没有包含任何元字符，，它可以匹配"testing"和"123testing"等字符串，但是不能匹配"Testing"。</font></p>
<p _extended="true"><font style="font-size: 14px" _extended="true">要想真正的用好正则表达式，正确的理解元字符是最重要的事情。下表列出了所有的元字符和对它们的一个简短的描述。</font></p>
<table cellspacing="2" cellpadding="2" _extended="true">
    <tbody _extended="true">
        <tr valign="baseline" _extended="true">
            <th align="left" _extended="true"><em _extended="true"><font style="font-size: 14px" _extended="true">元字符</font></em></th>
            <td _extended="true"><font style="font-size: 14px" _extended="true">&nbsp;</font></td>
            <th align="left" _extended="true"><em _extended="true"><font style="font-size: 14px" _extended="true">描述</font></em></th>
        </tr>
        <tr _extended="true">
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
        </tr>
        <tr _extended="true">
            <td valign="top" align="center" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">.</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">匹配任何单个字符。例如正则表达式<tt _extended="true">r.t</tt>匹配这些字符串：<em _extended="true">rat</em>、<em _extended="true">rut</em>、<em _extended="true">r t</em>，但是不匹配<em _extended="true">root</em>。&nbsp;</font></td>
        </tr>
        <tr _extended="true">
            <td valign="top" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">$</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">匹配行结束符。例如正则表达式<tt _extended="true">weasel$</tt> 能够匹配字符串"<em _extended="true">He's a weasel</em>"的末尾，但是不能匹配字符串"<em _extended="true">They are a bunch of weasels.</em>"。&nbsp;</font></td>
        </tr>
        <tr _extended="true">
            <td valign="top" _extended="true">
            <center _extended="true"><font style="font-size: 14px" _extended="true">^</font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true">匹配一行的开始。例如正则表达式<tt _extended="true">^When in</tt>能够匹配字符串"<em _extended="true">When in the course of human events</em>"的开始，但是不能匹配"<em _extended="true">What and When in the"。</em></font></font></td>
        </tr>
        <tr _extended="true">
            <td valign="top" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">*</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">匹配0或多个正好在它之前的那个字符。例如正则表达式<tt _extended="true">.*</tt>意味着能够匹配任意数量的任何字符。</font></td>
        </tr>
        <tr _extended="true">
            <td valign="top" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">\</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">这是引用府，用来将这里列出的这些元字符当作普通的字符来进行匹配。例如正则表达式<tt _extended="true">\$</tt>被用来匹配美元符号，而不是行尾，类似的，正则表达式<tt _extended="true">\.</tt>用来匹配点字符，而不是任何字符的通配符。</font></td>
        </tr>
        <tr _extended="true">
            <td valign="top" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">[ ]&nbsp;</tt><br _extended="true" />
            <tt _extended="true">[c1-c<font size="-1" _extended="true">2</font>]</tt><br _extended="true" />
            <tt _extended="true">[^c1-c<font size="-1" _extended="true">2</font>]</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">匹配括号中的任何一个字符。例如正则表达式<tt _extended="true">r[aou]t</tt>匹配<em _extended="true">rat</em>、<em _extended="true">rot</em>和<em _extended="true">rut</em>，但是不匹配<em _extended="true">ret</em>。可以在括号中使用连字符-来指定字符的区间，例如正则表达式<tt _extended="true">[0-9]</tt>可以匹配任何数字字符；还可以制定多个区间，例如正则表达式<tt _extended="true">[A-Za-z]</tt>可以匹配任何大小写字母。另一个重要的用法是&#8220;排除&#8221;，要想匹配<em _extended="true">除了</em>指定区间之外的字符——也就是所谓的补集——在左边的括号和第一个字符之间使用^字符，例如正则表达式<tt _extended="true">[^269A-Z]</tt> 将匹配除了2、6、9和所有大写字母之外的任何字符。</font></td>
        </tr>
        <tr _extended="true">
            <td valign="top" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">\&lt; \&gt;</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">匹配词（<em _extended="true">word</em>）的开始（\&lt;）和结束（\&gt;）。例如正则表达式<tt _extended="true">\&lt;the</tt>能够匹配字符串"<em _extended="true">for the wise</em>"中的"the"，但是不能匹配字符串"<em _extended="true">otherwise</em>"中的"the"。注意：这个元字符不是所有的软件都支持的。</font></td>
        </tr>
        <tr _extended="true">
            <td valign="top" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">\( \)</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">将 \( 和 \) 之间的表达式定义为&#8220;组&#8221;（<em _extended="true">group</em>），并且将匹配这个表达式的字符保存到一个临时区域（一个正则表达式中最多可以保存9个），它们可以用 <tt _extended="true">\1</tt> 到<tt _extended="true">\9</tt> 的符号来引用。</font></td>
        </tr>
        <tr _extended="true">
            <td valign="baseline" _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">|</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">将两个匹配条件进行逻辑&#8220;或&#8221;（<em _extended="true">Or</em>）运算。例如正则表达式<tt _extended="true">(him|her)</tt> 匹配"<em _extended="true">it belongs to him</em>"和"<em _extended="true">it belongs to her</em>"，但是不能匹配"<em _extended="true">it belongs to them.</em>"。注意：这个元字符不是所有的软件都支持的。</font></td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">+</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">匹配1或多个正好在它之前的那个字符。例如正则表达式<tt _extended="true">9+</tt>匹配9、99、999等。注意：这个元字符不是所有的软件都支持的。</font></td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">?</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">匹配0或1个正好在它之前的那个字符。注意：这个元字符不是所有的软件都支持的。</font></td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true">
            <center _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">\{</tt><em _extended="true">i</em><tt _extended="true">\}</tt><br _extended="true" />
            <tt _extended="true">\{</tt><em _extended="true">i</em><tt _extended="true">,</tt><em _extended="true">j</em><tt _extended="true">\}</tt></font></font></center></td>
            <td _extended="true">&nbsp;</td>
            <td valign="baseline" _extended="true"><font style="font-size: 14px" _extended="true">匹配指定数目的字符，这些字符是在它之前的表达式定义的。例如正则表达式<tt _extended="true">A[0-9]\{3\}</tt> 能够匹配字符"A"后面跟着正好3个数字字符的串，例如A123、A348等，但是不匹配A1234。而正则表达式<tt _extended="true">[0-9]\{4,6\}</tt> 匹配连续的任意4个、5个或者6个数字字符。注意：这个元字符不是所有的软件都支持的。</font></td>
        </tr>
    </tbody>
</table>
<hr width="100%" _extended="true" />
<p _extended="true"><font style="font-size: 14px" _extended="true">最简单的元字符是点，它能够匹配任何单个字符（注意不包括新行符）。假定有个文件test.txt包含以下几行内容：</font></p>
<div style="margin-left: 2em" _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">he is a rat</tt><br _extended="true" />
<tt _extended="true">he is in a rut</tt><br _extended="true" />
<tt _extended="true">the food is Rotten</tt><br _extended="true" />
<tt _extended="true">I like root beer</tt></font></font></div>
<font style="font-size: 14px" _extended="true">我们可以使用grep命令来测试我们的正则表达式，grep命令使用正则表达式去尝试匹配指定文件的每一行，并将至少有一处匹配表达式的所有行显示出来。命令</font>
<div style="margin-left: 2em" _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">grep r.t test.txt</tt></font></font></div>
<font style="font-size: 14px" _extended="true">在test.txt文件中的每一行中搜索正则表达式<tt _extended="true">r.t</tt>，并打印输出匹配的行。正则表达式<tt _extended="true">r.t</tt>匹配一个<tt _extended="true">r</tt>接着任何一个字符再接着一个<tt _extended="true">t</tt>。所以它将匹配文件中的<tt _extended="true">rat</tt>和<tt _extended="true">rut</tt>，而不能匹配<tt _extended="true">Rotten</tt>中的<tt _extended="true">Rot</tt>，因为正则表达式是大小写敏感的。要想同时匹配大写和小写字母，应该使用字符区间元字符（方括号）。正则表达式<tt _extended="true">[Rr]</tt>能够同时匹配<tt _extended="true">R</tt>和<tt _extended="true">r</tt>。所以，要想匹配一个大写或者小写的<tt _extended="true">r</tt>接着任何一个字符再接着一个<tt _extended="true">t</tt>就要使用这个表达式：<tt _extended="true">[Rr].t</tt>。</font>
<p _extended="true"><font style="font-size: 14px" _extended="true">要想匹配行首的字符要使用抑扬字符（<em _extended="true">^</em>）——又是也被叫做插入符。例如，想找到text.txt中行首"he"打头的行，你可能会先用简单表达式<tt _extended="true">he</tt>，但是这会匹配第三行的<tt _extended="true">the</tt>，所以要使用正则表达式<tt _extended="true">^he</tt>，它只匹配在行首出现的<tt _extended="true">h</tt>。</font></p>
<p _extended="true"><font style="font-size: 14px" _extended="true">有时候指定&#8220;除了&#215;&#215;&#215;都匹配&#8221;会比较容易达到目的，当抑扬字符（<em _extended="true">^</em>）出现在方括号中是，它表示&#8220;排除&#8221;，例如要匹配<tt _extended="true">he</tt> ，但是排除前面是<tt _extended="true">t</tt> or <tt _extended="true">s</tt>的情性（也就是<tt _extended="true">the</tt>和<tt _extended="true">she</tt>），可以使用：<tt _extended="true">[^st]he</tt>。</font></p>
<p _extended="true"><font style="font-size: 14px" _extended="true">可以使用方括号来指定多个字符区间。例如正则表达式<tt _extended="true">[A-Za-z]</tt>匹配任何字母，包括大写和小写的；正则表达式<tt _extended="true">[A-Za-z][A-Za-z]*</tt> 匹配一个字母后面接着0或者多个字母（大写或者小写）。当然我们也可以用元字符<tt _extended="true">+</tt>做到同样的事情，也就是：<tt _extended="true">[A-Za-z]+</tt> ，和<tt _extended="true">[A-Za-z][A-Za-z]*</tt>完全等价。但是要注意元字符<tt _extended="true">+</tt> 并不是所有支持正则表达式的程序都支持的。关于这一点可以参考后面的</font><a href="http://net.pku.edu.cn/~yhf/tao_regexps_zh.html#Regular%20Expressions%20Syntax" _extended="true"><font style="font-size: 14px" color="#000000" _extended="true">正则表达式语法支持情况</font></a><font style="font-size: 14px" _extended="true">。</font></p>
<p _extended="true"><font style="font-size: 14px" _extended="true">要指定特定数量的匹配，要使用大括号（注意必须使用反斜杠来转义）。想匹配所有<tt _extended="true">100</tt>和<tt _extended="true">1000</tt>的实例而排除<tt _extended="true">10</tt>和<tt _extended="true">10000</tt>，可以使用：<tt _extended="true">10\{2,3\}</tt>，这个正则表达式匹配数字1后面跟着2或者3个0的模式。在这个元字符的使用中一个有用的变化是忽略第二个数字，例如正则表达式<tt _extended="true">0\{3,\}</tt> 将匹配至少3个连续的0。</font></p>
<h2 _extended="true"><a id="SimpleCommands" name="SimpleCommands" _extended="true"></a><font style="font-size: 14px" _extended="true">简单的例子</font></h2>
<p _extended="true"><font style="font-size: 14px" _extended="true">这里有一些有代表性的、比较简单的例子。</font></p>
<table cellspacing="2" cellpadding="2" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><em _extended="true"><font style="font-size: 14px" _extended="true">vi 命令</font></em></td>
            <td _extended="true"><em _extended="true"><font style="font-size: 14px" _extended="true">作用</font></em></td>
        </tr>
        <tr _extended="true">
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" size="+1" _extended="true">:%s/ */ /g</font></tt></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">把一个或者多个空格替换为一个空格。</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" size="+1" _extended="true">:%s/ *$//</font></tt></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">去掉行尾的所有空格。</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" size="+1" _extended="true">:%s/^/ /</font></tt></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">在每一行头上加入一个空格。</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" size="+1" _extended="true">:%s/^[0-9][0-9]* //</font></tt></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">去掉行首的所有数字字符。</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" size="+1" _extended="true">:%s/b[aeio]g/bug/g</font></tt></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">将所有的<em _extended="true">bag</em>、<em _extended="true">beg</em>、<em _extended="true">big</em>和<em _extended="true">bog</em>改为<em _extended="true">bug</em>。&nbsp;</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" size="+1" _extended="true">:%s/t\([aou]\)g/h\1t/g</font></tt></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">将所有<em _extended="true">tag</em>、<em _extended="true">tog</em>和<em _extended="true">tug</em>分别改为<em _extended="true">hat</em>、<em _extended="true">hot</em>和<em _extended="true">hug</em>（注意用group的用法和使用\1引用前面被匹配的字符）。</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
        </tr>
    </tbody>
</table>
<h2 _extended="true"><a id="MediumDifficultyExamples" name="MediumDifficultyExamples" _extended="true"></a><font style="font-size: 14px" _extended="true">中级的例子（神奇的咒语）</font></h2>
<h3 _extended="true"><font style="font-size: 14px" _extended="true">例1</font></h3>
<p _extended="true"><font style="font-size: 14px" _extended="true">将所有方法foo(<em _extended="true">a,b,c</em>)的实例改为foo(<em _extended="true">b,a,c</em>)。这里a、b和c可以是任何提供给方法foo()的参数。也就是说我们要实现这样的转换：</font></p>
<table cellspacing="4" cellpadding="0" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><font style="font-size: 14px" _extended="true">之前</font></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">&nbsp;</font></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">之后</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">foo(10,7,2)</font></tt></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">foo(7,10,2)</font></tt></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">foo(x+13,y-2,10)</font></tt></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">foo(y-2,x+13,10)</font></tt></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">foo( bar(8), x+y+z, 5)</font></tt></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">foo( x+y+z, bar(8), 5)</font></tt></td>
        </tr>
    </tbody>
</table>
<p _extended="true"><font style="font-size: 14px" _extended="true">下面这条替换命令能够实现这一魔法：</font></p>
<div style="margin-left: 2em" _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">:%s/foo(\([^,]*\),\([^,]*\),\([^)]*\))/foo(\2,\1,\3)/g</tt></font></font></div>
<p _extended="true"><font style="font-size: 14px" _extended="true">现在让我们把它打散来加以分析。写出这个表达式的基本思路是找出foo()和它的括号中的三个参数的位置。第一个参数是用这个表达式来识别的：：<tt _extended="true">\([^,]*\)</tt>，我们可以从里向外来分析它：&nbsp;</font></p>
<table _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">[^,]</font></tt></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">&nbsp;</font></td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">除了逗号之外的任何字符</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">[^,]*</font></tt></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">0或者多个非逗号字符</font></td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">\([^,]*\)</font></tt></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">将这些非逗号字符标记为<tt _extended="true">\1</tt>，这样可以在之后的替换模式表达式中引用它</font></td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">\([^,]*\),</font></tt></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><font style="font-size: 14px" _extended="true">我们必须找到0或者多个非逗号字符后面跟着一个逗号，并且非逗号字符那部分要标记出来以备后用。</font></td>
        </tr>
    </tbody>
</table>
<p _extended="true"><font style="font-size: 14px" _extended="true">现在正是指出一个使用正则表达式常见错误的最佳时机。为什么我们要使用<tt _extended="true">[^,]*</tt>这样的一个表达式，而不是更加简单直接的写法，例如：<tt _extended="true">.*</tt>，来匹配第一个参数呢？设想我们使用模式<tt _extended="true">.*</tt>来匹配字符串"10,7,2"，它应该匹配"10,"还是"10,7,"？为了解决这个两义性（ambiguity），正则表达式规定一律按照最长的串来，在上面的例子中就是"10,7,"，显然这样就找出了两个参数而不是我们期望的一个。所以，我们要使用<tt _extended="true">[^,]*</tt>来强制取出第一个逗号之前的部分。</font></p>
<p _extended="true"><font style="font-size: 14px" _extended="true">这个表达式我们已经分析到了：<tt _extended="true">foo(\([^,]*\)</tt>，这一段可以简单的翻译为&#8220;当你找到<tt _extended="true">foo(</tt>就把其后直到第一个逗号之前的部分标记为<tt _extended="true">\1</tt>&#8221;。然后我们使用同样的办法标记第二个参数为<tt _extended="true">\2</tt>。对第三个参数的标记方法也是一样，只是我们要搜索所有的字符直到右括号。我们并没有必要去搜索第三个参数，因为我们不需要调整它的位置，但是这样的模式能够保证我们只去替换那些有三个参数的foo()方法调用，在foo()是一个重载（overoading）方法时这种明确的模式往往是比较保险的。然后，在替换部分，我们找到foo()的对应实例，然后利用标记好的部分进行替换，是的第一和第二个参数交换位置。</font></p>
<h3 _extended="true"><font style="font-size: 14px" _extended="true">例2</font></h3>
<font style="font-size: 14px" _extended="true">假设有一个CSV（comma separated value）文件，里面有一些我们需要的信息，但是格式却有问题，目前数据的列顺序是：姓名，公司名，州名缩写，邮政编码，现在我们希望讲这些数据重新组织，以便在我们的某个软件中使用，需要的格式为：姓名，州名缩写-邮政编码，公司名。也就是说，我们要调整列顺序，还要合并两个列来构成一个新列。另外，我们的软件不能接受逗号前后面有任何空格（包括空格和制表符）所以我们还必须要去掉逗号前后的所有空格。</font>
<p _extended="true"><font style="font-size: 14px" _extended="true">这里有几行我们现在的数据：</font></p>
<div style="margin-left: 2em" _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">Bill Jones,&nbsp;&nbsp;&nbsp;&nbsp; HI-TEK Corporation ,&nbsp; CA, 95011</tt><br _extended="true" />
<tt _extended="true">Sharon Lee Smith,&nbsp; Design Works Incorporated,&nbsp; CA, 95012</tt><br _extended="true" />
<tt _extended="true">B. Amos&nbsp;&nbsp; ,&nbsp; Hill Street Cafe,&nbsp; CA, 95013</tt><br _extended="true" />
<tt _extended="true">Alexander Weatherworth,&nbsp; The Crafts Store,&nbsp; CA, 95014</tt><br _extended="true" />
<tt _extended="true">...</tt></font></font></div>
<font style="font-size: 14px" _extended="true">我们希望把它变成这个样子：</font>
<div style="margin-left: 2em" _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">Bill Jones,CA 95011,HI-TEK Corporation</tt><br _extended="true" />
<tt _extended="true">Sharon Lee Smith,CA 95012,Design Works Incorporated</tt><br _extended="true" />
<tt _extended="true">B. Amos,CA 95013,Hill Street Cafe</tt><br _extended="true" />
<tt _extended="true">Alexander Weatherworth,CA 95014,The Crafts Store</tt><br _extended="true" />
<tt _extended="true">...</tt></font></font></div>
<font style="font-size: 14px" _extended="true">我们将用两个正则表达式来解决这个问题。第一个移动列和合并列，第二个用来去掉空格。</font>
<p _extended="true"><font style="font-size: 14px" _extended="true">下面就是第一个替换命令：</font></p>
<div style="margin-left: 2em" _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">:%s/\([^,]*\),\([^,]*\),\([^,]*\),\(.*\)/\1,\3 \4,\2/</tt></font></font></div>
<font style="font-size: 14px" _extended="true">这里的方法跟例1基本一样，第一个列（姓名）用这个表达式来匹配：<tt _extended="true">\([^,]*\)</tt>，即第一个逗号之前的所有字符，而姓名内容被用<tt _extended="true">\1</tt>标记下来。公司名和州名缩写字段用同样的方法标记为<tt _extended="true">\2</tt>和<tt _extended="true">\3</tt>，而最后一个字段用<tt _extended="true">\(.*\)</tt>来匹配（"匹配所有字符直到行末"）。替换部分则引用上面标记的那些内容来进行构造。</font>
<p _extended="true"><font style="font-size: 14px" _extended="true">下面这个替换命令则用来去除空格：</font></p>
<div style="margin-left: 2em" _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">:%s/[ \t]*,[ \t]*/,/g</tt></font></font></div>
<font style="font-size: 14px" _extended="true">我们还是分解来看：<tt _extended="true">[ \t]</tt>匹配空格/制表符，<tt _extended="true">[ \t]*</tt> 匹配0或多个空格/制表符，<tt _extended="true">[ \t]*</tt>,匹配0或多个空格/制表符后面再加一个逗号，最后，<tt _extended="true">[ \t]*,[ \t]*</tt>匹配0或多个空格/制表符接着一个逗号再接着0或多个空格/制表符。在替换部分，我们简单的我们找到的所有东西替换成一个逗号。这里我们使用了结尾的可选的<tt _extended="true">g</tt>参数，这表示在每行中对所有匹配的串执行替换（而不是缺省的只替换第一个匹配串）。</font>
<h3 _extended="true"><font style="font-size: 14px" _extended="true">例3</font></h3>
<font style="font-size: 14px" _extended="true">假设有一个多字符的片断重复出现，例如：</font>
<blockquote _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">Billy tried really hard</tt><br _extended="true" />
<tt _extended="true">Sally tried really really hard</tt><br _extended="true" />
<tt _extended="true">Timmy tried really really really hard</tt><br _extended="true" />
<tt _extended="true">Johnny tried really really really really hard</tt></font></font></blockquote><font style="font-size: 14px" _extended="true">而你想把"really"、"really really"，以及任意数量连续出现的"really"字符串换成一个简单的"very"（simple is good!），那么以下命令：</font>
<blockquote _extended="true"><tt _extended="true"><font style="font-size: 14px" _extended="true">:%s/\(really \)\(really \)*/very /</font></tt></blockquote><font style="font-size: 14px" _extended="true">就会把上述的文本变成：</font>
<blockquote _extended="true"><font style="font-size: 16px" _extended="true"><font style="font-size: 14px" _extended="true"><tt _extended="true">Billy tried very hard</tt><br _extended="true" />
<tt _extended="true">Sally tried very hard</tt><br _extended="true" />
<tt _extended="true">Timmy tried very hard</tt><br _extended="true" />
<tt _extended="true">Johnny tried very hard</tt></font></font></blockquote><font style="font-size: 14px" _extended="true">表达式<tt _extended="true">\(really \)*</tt>匹配0或多个连续的"really "（注意结尾有个空格），而<tt _extended="true">\(really \)\(really \)*</tt> 匹配1个或多个连续的"really "实例。</font>
<h2 _extended="true"><a id="HardExamples" name="HardExamples" _extended="true"></a><font style="font-size: 14px" _extended="true">困难的例子（不可思议的象形文字）</font></h2>
<div class="middleSize" id="articleContent" _extended="true">
<div style="text-indent: 2em" _extended="true">
<h1 _extended="true"><a id="Regular_Expressions_In_Various_Tools" name="Regular_Expressions_In_Various_Tools" _extended="true"></a>不同工具中的正则表达式</h1>
OK，你已经准备使用RE（regular expressions，正则表达式），但是你并准备使用vi。所以，在这里我们给出一些在其他工具中使用RE的例子。另外，我还会总结一下你在不同程序之间使用RE可能发现的区别。
<p _extended="true">当然，你也可以在Visual C++编辑器中使用RE。选择Edit-&gt;Replace，然后选择"Regular expression"选择框，Find What输入框对应上面介绍的vi命令<strong _extended="true"><tt _extended="true">:%s/pat1/pat2/g</tt></strong>中的pat1部分，而Replace输入框对应pat2部分。但是，为了得到vi的执行范围和<strong _extended="true"><tt _extended="true">g</tt></strong>选项，你要使用Replace All或者适当的手工Find Next and Replace（译者按：知道为啥有人骂微软弱智了吧，虽然VC中可以选中一个范围的文本，然后在其中执行替换，但是总之不够vi那么灵活和典雅）。</p>
<h2 _extended="true">sed</h2>
<p _extended="true">Sed是<strong _extended="true"><u _extended="true">S</u></strong>tream <strong _extended="true"><u _extended="true">ED</u></strong>itor的缩写，是Unix下常用的基于文件和管道的编辑工具，可以在手册中得到关于sed的详细信息。</p>
<p _extended="true">这里是一些有趣的sed脚本，假定我们正在处理一个叫做price.txt的文件。注意这些编辑并不会改变源文件，sed只是处理源文件的每一行并把结果显示在标准输出中（当然很容易使用重定向来定制）：</p>
<table _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><em _extended="true">sed脚本</em></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><strong _extended="true"><em _extended="true">描述</em></strong></td>
        </tr>
        <tr _extended="true">
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">sed 's/^$/d' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">删除所有空行</td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">sed 's/^[ \t]*$/d' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">删除所有只包含空格或者制表符的行</td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">sed 's/"//g' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">删除所有引号</td>
        </tr>
    </tbody>
</table>
<h2 _extended="true">awk</h2>
awk是一种编程语言，可以用来对文本数据进行复杂的分析和处理。可以在手册中得到关于awk的详细信息。这个古怪的名字是它作者们的姓的缩写（Aho，Weinberger和Kernighan）。
<p _extended="true">在Aho，Weinberger和Kernighan的书<u _extended="true">The AWK Programming Language</u>中有很多很好的awk的例子，请不要让下面这些微不足道的脚本例子限制你对awk强大能力的理解。我们同样假定我们针对price.txt文件进行处理，跟sed一样，awk也只是把结果显示在终端上。&nbsp;</p>
<table _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><em _extended="true">awk脚本</em></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true"><strong _extended="true"><em _extended="true">描述</em></strong></td>
        </tr>
        <tr _extended="true">
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">awk '$0 !~ /^$/' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">删除所有空行</td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">awk 'NF &gt; 0' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">awk中一个更好的删除所有行的办法</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">awk '$2 ~ /^[JT]/ {print $3}' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有第二个字段是'J'或者'T'打头的行中的第三个字段</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td noWrap _extended="true"><strong _extended="true"><tt _extended="true">awk '$2 !~ /[Mm]isc/ {print $3 + $4}' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">针对所有第二个字段不包含'Misc'或者'misc'的行，打印第3和第4列的和（假定为数字）</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">awk '$3 !~ /^[0-9]+\.[0-9]*$/ {print $0}' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有第三个字段不是数字的行，这里数字是指<tt _extended="true">d.d</tt>或者<tt _extended="true">d这样的形式，其中</tt><tt _extended="true">d</tt>是0到9的任何数字</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">awk '$2 ~ /John|Fred/ {print $0}' price.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">如果第二个字段包含'John'或者'Fred'则打印整行</td>
        </tr>
    </tbody>
</table>
<h2 _extended="true">grep</h2>
grep是一个用来在一个或者多个文件或者输入流中使用RE进行查找的程序。它的name编程语言可以用来针对文件和管道进行处理。可以在手册中得到关于grep的完整信息。这个同样古怪的名字来源于vi的一个命令，<strong _extended="true"><tt _extended="true">g/</tt></strong><em _extended="true">re</em><strong _extended="true"><tt _extended="true">/p</tt></strong>，意思是<strong _extended="true">g</strong>lobal <strong _extended="true">r</strong>egular <strong _extended="true">e</strong>xpression <strong _extended="true">p</strong>rint。
<p _extended="true">下面的例子中我们假定在文件phone.txt中包含以下的文本，——其格式是姓加一个逗号，然后是名，然后是一个制表符，然后是电话号码：</p>
<div style="margin-left: 2em" _extended="true">
<p _extended="true"><tt _extended="true">Francis, John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5-3871</tt><br _extended="true" />
<tt _extended="true">Wong, Fred&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4-4123</tt><br _extended="true" />
<tt _extended="true">Jones, Thomas&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1-4122</tt><br _extended="true" />
<tt _extended="true">Salazar, Richard&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5-2522</tt></p>
</div>
<table _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><em _extended="true">grep命令</em></strong></td>
            <td _extended="true"><strong _extended="true"><em _extended="true">&nbsp;</em></strong></td>
            <td _extended="true"><strong _extended="true"><em _extended="true">描述</em></strong></td>
        </tr>
        <tr _extended="true">
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">grep '\t5-...1' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">把所有电话号码以5开头以1结束的行打印出来，注意制表符是用<strong _extended="true"><tt _extended="true">\t</tt></strong>表示的</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td noWrap _extended="true"><strong _extended="true"><tt _extended="true">grep '^S[^ ]* R' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有姓以S打头和名以R打头的行</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">grep '^[JW]' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有姓开头是J或者W的行</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">grep ', ....\t' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有姓是4个字符的行，注意制表符是用<strong _extended="true"><tt _extended="true">\t</tt></strong>表示的</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">grep -v '^[JW]' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有不以J或者W开头的行</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">grep '^[M-Z]' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有姓的开头是M到Z之间任一字符的行</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">grep '^[M-Z].*[12]' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有姓的开头是M到Z之间任一字符，并且点号号码结尾是1或者2的行</td>
        </tr>
    </tbody>
</table>
<h2 _extended="true">egrep</h2>
egrep是grep的一个扩展版本，它在它的正则表达式中支持更多的元字符。下面的例子中我们假定在文件phone.txt中包含以下的文本，——其格式是姓加一个逗号，然后是名，然后是一个制表符，然后是电话号码：
<div style="margin-left: 2em" _extended="true"><tt _extended="true">Francis, John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5-3871</tt><br _extended="true" />
<tt _extended="true">Wong, Fred&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4-4123</tt><br _extended="true" />
<tt _extended="true">Jones, Thomas&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1-4122</tt><br _extended="true" />
<tt _extended="true">Salazar, Richard&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5-2522</tt></div>
<table _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><em _extended="true">egrep command</em></strong></td>
            <td _extended="true"><strong _extended="true"><em _extended="true">&nbsp;</em></strong></td>
            <td _extended="true"><strong _extended="true"><em _extended="true">Description</em></strong></td>
        </tr>
        <tr _extended="true">
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">
            <hr width="100%" _extended="true" />
            </td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">egrep '(John|Fred)' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有包含名字<em _extended="true">John</em>或者<em _extended="true">Fred</em>的行</td>
        </tr>
        <tr valign="baseline" _extended="true">
            <td noWrap _extended="true"><strong _extended="true"><tt _extended="true">egrep 'John|22$|^W' phone.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">打印所有包含<em _extended="true">John</em> 或者以22结束或者以<em _extended="true">W</em>的行</td>
        </tr>
        <tr _extended="true">
            <td _extended="true"><strong _extended="true"><tt _extended="true">egrep 'net(work)?s' report.txt</tt></strong></td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">从report.txt中找到所有包含<em _extended="true">networks</em>或者<em _extended="true">nets</em>的行</td>
        </tr>
    </tbody>
</table>
<hr width="100%" _extended="true" />
<h1 _extended="true"><a name="Regular Expressions Syntax" _extended="true"></a>正则表达式语法支持情况</h1>
<table cellspacing="0" border="1" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td _extended="true"><strong _extended="true">命令或环境</strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">.</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">[ ]</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">^</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">$</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">\( \)</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">\{ \}</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">?</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">+</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">|</font></tt></strong></td>
            <td _extended="true"><strong _extended="true"><tt _extended="true"><font face="Courier New" _extended="true">( )</font></tt></strong></td>
        </tr>
        <tr _extended="true">
            <td _extended="true">vi</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">Visual C++</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">awk</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">sed</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">Tcl</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">ex</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">grep</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">egrep</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">fgrep</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;X&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;</td>
        </tr>
        <tr _extended="true">
            <td _extended="true">perl</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X</td>
            <td _extended="true">&nbsp;X</td>
        </tr>
    </tbody>
</table>
<p _extended="true">&nbsp;</p>
<hr _extended="true" />
<h1 _extended="true"><a id="ViSubstitutionCommandSyntax" name="ViSubstitutionCommandSyntax" _extended="true"></a>vi替换命令简介</h1>
Vi的替换命令：
<div style="margin-left: 2em" _extended="true"><strong _extended="true"><tt _extended="true">:</tt></strong><em _extended="true">range</em><strong _extended="true"><tt _extended="true">s/</tt></strong><em _extended="true">pat1</em><strong _extended="true"><tt _extended="true">/</tt></strong><em _extended="true">pat2</em><strong _extended="true"><tt _extended="true">/g</tt></strong></div>
其中
<div style="margin-left: 2em" _extended="true"><strong _extended="true"><tt _extended="true">:</tt></strong> 这是Vi的命令执行界面。</div>
<div style="margin-left: 2em" _extended="true"><em _extended="true">range</em> 是命令执行范围的指定，可以使用百分号（%）表示所有行，使用点（.）表示当前行，使用美元符号（$）表示最后一行。你还可以使用行号，例如<strong _extended="true"><tt _extended="true">10,20</tt></strong>表示第10到20行，<strong _extended="true"><tt _extended="true">.,$</tt></strong>表示当前行到最后一行，<strong _extended="true"><tt _extended="true">.+2,$-5</tt></strong>表示当前行后两行直到全文的倒数第五行，等等。
<p _extended="true"><strong _extended="true"><tt _extended="true">s</tt></strong> 表示其后是一个替换命令。</p>
<p _extended="true"><em _extended="true">pat1</em> 这是要查找的一个正则表达式，这篇文章中有一大堆例子。</p>
</div>
<div style="margin-left: 2em" _extended="true"><em _extended="true">pat2</em> 这是希望把匹配串变成的模式的正则表达式，这篇文章中有一大堆例子。
<p _extended="true"><strong _extended="true"><tt _extended="true">g</tt></strong> 可选标志，带这个标志表示替换将针对行中每个匹配的串进行，否则则只替换行中第一个匹配串。</p>
</div>
网上有很多vi的在线手册，你可以访问他们以获得更加完整的信息。</div>
</div>
<img src ="http://www.blogjava.net/conans/aggbug/209563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-20 22:46 <a href="http://www.blogjava.net/conans/articles/209563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>