<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[汤姆·廖的博客 - 计算机]]></title>
<link>http://www.tomliao.cn/</link>
<description><![CDATA[分享生活、学习、计算机、教学等方面的博客]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog3 v2.8]]></copyright>
<webMaster><![CDATA[gang2005188[at]sina.com(小刚)]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>汤姆·廖的博客</title>
	<url>http://www.tomliao.cn/images/logos.gif</url>
	<link>http://www.tomliao.cn/</link>
	<description>汤姆·廖的博客</description>
</image>

			<item>
			<link>http://www.tomliao.cn/article/computer/216.htm</link>
			<title><![CDATA[IIS下moodle不能正常链接文件的问题解决办法]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Tue,30 Mar 2010 10:58:06 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=216</guid>
		<description><![CDATA[今天上午帮同学解决了一个在IIS下moodle不能连接文件的问题。解决办法如下：<br/>IIS默认不能支持Rewrite功能，所以moodle的链接文件的地址如：http:/localhost/moodle/file.php/5/test.txt 这样的地址是访问不了的。而apache则可以自动转到http:/localhost/moodle/file.php?file=/5/test.txt形式的地址。要在IIS下访问的一个办法为：用管理员身份登入，然后查找slashargument设置为否，即可。系统就自动使用第二种方法来链接文件。<br/><br/>网上还有一种方法就是要写ISAPI，做伪静态，方法如下，不过我没试过。<br/>1.到这里 <a href="http://www.isapirewrite.com/." target="_blank" rel="external">http://www.isapirewrite.com/.</a> 下载 ISAPI_Rewrite Lite version ，免费版本. <br/>运行下载的软件. <br/>2.打开软件安装所在的目录下的httpd.ini文件，一般默认目录为 C:\Program Files\Helicon\ISAPI_Rewrite\ <br/>3打开后httpd.ini 的内容如下：<br/>&nbsp;&nbsp;&nbsp;&nbsp; [ISAPI_Rewrite]<br/>&nbsp;&nbsp;&nbsp;&nbsp; # Defend your computer from some worm attacks<br/>&nbsp;&nbsp;&nbsp;&nbsp; RewriteRule .*(?:global.asa|default\.ida|root\.exe|\.\.).* . [F,I,O] <br/>4.添加规则如下:<br/>&nbsp;&nbsp;&nbsp;&nbsp; RewriteRule (.*?\.php)(\/.+) $1\?file=$2 [N,I]<br/>&nbsp;&nbsp;&nbsp;&nbsp; RewriteRule ^([^\?]+?\.php)(\/.+)$ $1\?file=$2 [QSA] <br/>5.重新启动IIS. <br/>用第一种方法弄好了，如果不考虑性能方面应该是可以的了，使用伪静态可以支持缓存，减轻服务器负担，可以搜索优化。]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/215.htm</link>
			<title><![CDATA[收集使用CSS的几个技巧]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Sat,27 Mar 2010 10:18:14 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=215</guid>
		<description><![CDATA[1.用正确的顺序指定链接的样式 <br/>当你用 CSS 来定义链接的多个状态样式时，要注意它们书写的顺序，正确的顺序是：:link :visited :hover :active。抽取第一个字母是&#34;LVHA&#34;，你可以记忆成&#34;LoVe HAte&#34;(喜欢讨厌)。为什么这么定义，可以参考 Eric Meyer 的《Link Specificity》。&nbsp;&nbsp;如果你的用户需要用键盘来控制，需要知道当前链接的焦点，你还可以定义:focus 属性。:focus 属性的效果也取决与你书写的位置，如果你希望聚焦元素显示:hover 效果，你就把:focus 写在:hover 前面；如果你希望聚焦效果替代:hover 效果，你就把:focus 放在:hover 后面。<br/>2. (a)在 IE中隐藏一个 CSS 定义，你可以使用子选择器(child sel&#101;ctor): <br/>html&gt;body p {&nbsp;&nbsp;<br/>/* 定义内容 */&nbsp;&nbsp;<br/>}&nbsp;&nbsp;<br/>(b)下面这个写法只有 IE 浏览器可以理解(对其他浏览器都隐藏)&nbsp;&nbsp;<br/>* html p {&nbsp;&nbsp;<br/>/* declarations */&nbsp;&nbsp;<br/>}&nbsp;&nbsp;<br/>(c)还有些时候，你希望 IE/Win 有效而 IE/Mac 隐藏，你可以使用&#34;反斜线&#34;技巧： <br/>/* \*/&nbsp;&nbsp;<br/>* html p {&nbsp;&nbsp;<br/>declarations&nbsp;&nbsp;<br/>}&nbsp;&nbsp;<br/>/* */&nbsp;&nbsp;<br/>条件注释(conditional comments)的方法&nbsp;&nbsp;<br/>另外一种方法，我认为比 CSS&nbsp;&nbsp;Hacks 更加经得起考验就是采用微软的私有属性条件注释(conditional comments)。<br/>用这个方法你可以给 IE单独定义一些样式，而不影响主样式表的定义。就象这样： <br/>&lt;!--[if IE]&gt;&nbsp;&nbsp;<br/>&lt;link rel=&#34;stylesheet&#34; type=&#34;text/css&#34; href=&#34;ie.css&#34; /&gt;&nbsp;&nbsp;<br/>&lt;![endif]--&gt;]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/211.htm</link>
			<title><![CDATA[moodel日历显示乱码的解决办法]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Tue,09 Mar 2010 15:41:31 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=211</guid>
		<description><![CDATA[<p>前两天帮一个同学弄一个moodel平台，弄好后安装中文语言包后，日历部分显示为乱码，经过分析，自己发现一个可以解决的办法，希望能为遇到此类问题的博友提供参考。<br />
首先，我谷歌一下，原来很多人也有这种问题，解决办法是将\lang\zh_cn_utf8下的langconfig.php的文件格式由utf-8改为ANSI格式，改完后日历部分的乱码是正常了，但是语言选项下拉列表的&ldquo;简体中文&rdquo;却变成乱码。有点顾此失彼的味道。于是我想能不能只改日历的编码呢。于是还是不变文件本身的编码，只是在文件中将日历的年月等相关的变量的编码用一个iconv的函数来改变编码。于是问题就解决了。最后的代码是<br />
&nbsp;</p>
<div class="codeText">
<div class="codeHead">PHP代码</div>
<ol class="dp-c">
    <li class="alt"><span><span>&lt;?php &nbsp;&nbsp;</span></span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'alphabet'</span><span>]&nbsp;=&nbsp;</span><span class="string">'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z'</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'backupnameformat'</span><span>]&nbsp;=&nbsp;</span><span class="string">'%%Y%%m%%d-%%H%%M'</span><span>; &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'firstdayofweek'</span><span>]&nbsp;=&nbsp;</span><span class="string">'1'</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'locale'</span><span>]&nbsp;=&nbsp;</span><span class="string">'zh_CN.UTF-8'</span><span>; &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'localewin'</span><span>]&nbsp;=&nbsp;</span><span class="string">'Chinese_China.936'</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'localewincharset'</span><span>]&nbsp;=&nbsp;</span><span class="string">'CP936'</span><span>; &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'nativecharset'</span><span>]&nbsp;=&nbsp;</span><span class="string">'GB18030'</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'nameedit'</span><span>]&nbsp;=&nbsp;</span><span class="string">'LF'</span><span>; &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'oldcharset'</span><span>]&nbsp;=&nbsp;</span><span class="string">'UTF-8'</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'strftimedate'</span><span>]&nbsp;=&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%Y年%%m月%%d日'</span><span>); &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'strftimedateshort'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%m月%%d日'</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'strftimedatetime'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%Y年%%m月%%d日&nbsp;%%H:%%M'</span><span>); &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'strftimedaydate'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%Y年%%m月%%d日&nbsp;%%A'</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'strftimedaydatetime'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%Y年%%m月%%d日&nbsp;%%A&nbsp;%%H:%%M'</span><span>); &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'strftimedayshort'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%m月%%d日&nbsp;%%A'</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'strftimedaytime'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%A&nbsp;%%H:%%M'</span><span>); &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'strftimemonthyear'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%Y年%%m月'</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'strftimerecent'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%m月%%d日&nbsp;%%H:%%M'</span><span>); &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'strftimerecentfull'</span><span>]&nbsp;=&nbsp;&nbsp;iconv(</span><span class="string">&quot;utf-8&quot;</span><span>,&nbsp;</span><span class="string">&quot;gb2312//IGNORE&quot;</span><span>,</span><span class="string">'%%Y年%%m月%%d日&nbsp;%%A&nbsp;%%H:%%M'</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'strftimetime'</span><span>]&nbsp;=&nbsp;</span><span class="string">'%%H:%%M'</span><span>; &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'thischarset'</span><span>]&nbsp;=&nbsp;</span><span class="string">'UTF-8'</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="vars">$string</span><span>[</span><span class="string">'thisdirection'</span><span>]&nbsp;=&nbsp;</span><span class="string">'ltr'</span><span>; &nbsp;&nbsp;</span></li>
    <li><span class="vars">$string</span><span>[</span><span class="string">'thislanguage'</span><span>]&nbsp;=&nbsp;</span><span class="string">'简体中文'</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>?&gt; &nbsp;&nbsp;</span></li>
</ol>
</div>
<p>&nbsp;</p>]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/207.htm</link>
			<title><![CDATA[header(&#34;Location:&#34;)应该注意的几个问题]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Wed,13 Jan 2010 11:40:58 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=207</guid>
		<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;header(&#34;Location:&#34;)作为php的转向语句。其实在使用中，他有几点需要注意的地方。<br/><br/> <br/><br/>1、要求header前没有任何输出<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;但是很多时候在header前我们已经输出了好多东西了，但是此时如果再次header的话，显然是出错的，在这里我们启用了一个ob的概念，这个东东的意思是在服务器端先存储有关输出，等待适当的时机再输出，而不是像现在这样运行一句，输出一句,发现header语句就只能报错了。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;具体的语句有： ob_start(); ob_end_clean();ob_flush();.........<br/><br/> <br/><br/>2、在header(&#34;Location:&#34;)后要及时exit<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;否则他是会继续执行的，虽然在浏览器端你看不到相应的数据出现，但是如果你进行抓包分析的话，你就会看到下面的语句也是在执行的。而且被输送到了浏览器客户端，只不过是没有被浏览器执行为html而已（浏览器执行了header进行了转向操作）。<br/><br/> <br/><br/>所以,标准的使用方法是：<br/><br/>ob_start();<br/><br/>........<br/><br/>if ( something ){<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ob_end_clean();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; header(&#34;Location: yourlocation&#34;)；<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; exit;<br/><br/>else{<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ..........<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ob_flush();&nbsp;&nbsp;//可省略<br/><br/>}(苏南)<br/><br/><br/>文章出处：DIY部落(<a href="http://www.diybl.com/course/4_webprogram/php/phpshil/2007828/69912.html" target="_blank" rel="external">http://www.diybl.com/course/4_webprogram/php/phpshil/2007828/69912.html</a>)]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/199.htm</link>
			<title><![CDATA[IE的坏脾气 - 盒模型Bug]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Mon,02 Nov 2009 12:07:58 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=199</guid>
		<description><![CDATA[<p>想要创建出漂亮的网页设计，除了要认真学习每一个html和CSS代码之外，不可能不去了解一下臭名昭著的IE6和更早的那些IE浏览器的坏脾气，因为你本来写出的规规矩矩的代码，漂亮的设计就此就要完成了，却发现呈现出的效果压根不是你所期望的那样，漂亮的布局被破坏的体无完肤。更可气的是当你查找一遍代码中的错误时，却压根找不出来。这时候你就迫切需要了解一下IE6和它的那些同伙的坏脾气了，因为很可能它们就是罪魁祸首。到底IE6的那几个家伙们到底是如何搞乱你的设计的？别急，让我来一一介绍。</p>
<p><strong>一、什么是盒模型（Box Model）？</strong></p>
<p>在CSS中，CSS将网页中的每一个段落、标题、图片等元素都看成是一个装在盒子里的东西，也就是盒子里的内容。比较让人好理解一些的一个比喻是一个大纸盒子里装了一块方形的面包。面包就是一个段落、一个标题或者一幅图片，面包比盒子要小一些。面包的边缘到盒子侧边的距离就是CSS中的内边距属性（Padding），盒子的侧面四个边形成的边框就是CSS中的Border属性，而一个网页中有很多段落、标题、图片，也就是有很多这样的盒子，这些盒子和盒子之间的距离就是CSS中的外边距属性（margin）。看看下图也许你能一下就明白：</p>
<p align="center"><img border="0" alt="ct_boxmodel" width="500" height="500" src="http://www.tomliao.cn/attachments/month_0911/0200911212615.gif" /></p>
<p><strong>二、什么是IE中的盒模型Bug？</strong></p>
<p>那么这些装着面包的盒子在IE中会出什么问题呢？首先，在IE6，包括IE6以上的IE版本中，对于盒模型的解析没有什么问题，而在低于IE6的IE版本中，IE在解析盒模型时会有一些问题出现。让我来举例说明。</p>
<p>首先，我们来定义一个盒子：</p>
<p>&nbsp;</p>
<p>
<table border="0" cellspacing="0" cellpadding="6" width="95%" align="center" style="border-bottom: #0099cc 1px solid; border-left: #0099cc 1px solid; table-layout: fixed; border-top: #0099cc 1px solid; border-right: #0099cc 1px solid">
    <tbody>
        <tr>
            <td bgcolor="#ddedfb" style="word-wrap: break-word"><font color="#ff0000">以下为引用的内容：</font><br />
            p{ <br />
            &nbsp;&nbsp; border:10px solid #3b5998;&nbsp; <br />
            &nbsp;&nbsp; padding:30px;&nbsp; <br />
            &nbsp;&nbsp; width:200px; <br />
            }</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p>标准情况下，这个盒的宽度应该是：10+10+30+30+200=280px。但是在IE5.0浏览器中，对盒模型的宽度解释有个bug，它会认为200px是整个盒的总宽度，那么如果这样解释的话，内容的宽度变成：200-10-10-30-30=120px。下面是两者的对比图：</p>
<p align="center"><img alt="" src="http://www.tomliao.cn/attachments/month_0911/6200911212655.png" /></p>
<p align="center"><img alt="" src="http://www.tomliao.cn/attachments/month_0911/o200911212750.png" /></p>
<p><strong>三、如何解决盒模型Bug这个问题呢？</strong></p>
<p>其实对这个问题完全可以置之不理，因为目前全球使用IE6以下版本的人数应该是屈指可数了，我们也在经过盗版XP的洗礼下，整体上都更新到了IE6.0。当然，如果你要网页保持完美的话，要弥补这个bug，可以采用这样一个技巧：即增加一个IE5不能解释的声音属性&ldquo;voice-family&rdquo;，读到这个定义时浏览器就不再继续阅读，认为宽度就是280px，而其他符合标准的浏览器会继续阅读，并执行第二个真实值200px。CSS代码如下：</p>
<p>&nbsp;</p>
<p>
<table border="0" cellspacing="0" cellpadding="6" width="95%" align="center" style="border-bottom: #0099cc 1px solid; border-left: #0099cc 1px solid; table-layout: fixed; border-top: #0099cc 1px solid; border-right: #0099cc 1px solid">
    <tbody>
        <tr>
            <td bgcolor="#ddedfb" style="word-wrap: break-word"><font color="#ff0000">以下为引用的内容：</font><br />
            p{ <br />
            border:10px solid #3b5998; <br />
            padding:30px; <br />
            width :280px; <br />
            voice-family:&quot;\&quot;}\&quot;&quot;; <br />
            voice-family:inherit; <br />
            width:200px; <br />
            }</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p>关于voice-family属性的功能，主要是把文档转化为纯文本，然后传给屏幕阅读器（可读出屏幕上所有字符的一种程序）。是用来帮助视觉能力低弱的人士，或者在家庭娱乐和汽车中使用的，平时我们几乎用不到这个CSS属性。（<a href="http://startwmlife.com/?p=1184" target="_blank">原文地址</a>）</p>]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/198.htm</link>
			<title><![CDATA[CSS教程：关于CSS框架网页设计]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Tue,27 Oct 2009 20:19:37 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=198</guid>
		<description><![CDATA[　　1、css框架 <br/><br/>　　中国的互联网行业已经发展了10年，浏览器也从最早流行的NS到现在的FF3.IE7等等……前端开发工程师的职位也诞生了。近几年在web开发中，有个非常火的词——“框架”。YUI、JQuery、Prototype这些javascript框架在开发网站时，确实成为前端开发工程师的手中利器。为什么呢？因为框架是包含工具、函数库、约定，以及尝试从常用任务中抽象出可以复用的通用模块，让设计师与程序员避免重复开发。通俗地讲便是把大多数重复工作的时间给节约了。 <br/><br/>　　编写css也是一样，从最初只是定义文字颜色、内容排版，到现在定义所有的表现。css框架也渐渐被重视了，因为大家都认识到：从具象的表现中抽出抽象的模块来重复使用，是减少用户下载、方便团队及个人开发最重要的手段。 <br/><br/>　　2、css框架的开发顺序 <br/><br/>　　a) 格式化 reset.css <br/><br/>　　格式化css的真正好处是能够快速启动工作，你可以在新的HTML文件里引入框架，不用再处理重置padding 和 margins，实现统一的排版、浏览器下的相同表现。 <br/><br/>　　b) 布局 layout.css <br/><br/>　　定义页面是二栏还是三栏，是全屏还是1024×768…… <br/><br/>　　一个网站的设计可能有很多种布局，但是大多数都是由几个具有复用性的布局组成，选择性的引入所需要的布局，可以很快地应用所期望的页面布局。 <br/><br/>　　c) 基本样式 type.css <br/><br/>　　定义body、h1-h6、a:link-a:active、p等的字体大小和颜色。 <br/><br/>　　基本样式的css引用，譬如将ul定义class为“ul-text”，用来展现相同的icon、行间距、链接色彩。 <br/><br/>　　还可以像这样应用：class=”ul-text square”，li前展现的是方型的icon。 <br/><br/>　　d) 表格修饰 table.css <br/><br/>　　定义table、tr、td、th、thead、tfoot、tbody、caption等标签的表现。 <br/><br/>　　和基本样式一样，但是表格在现有网站的展现形式几乎都是处理数据，所以分开存放引用。譬如在table上应用table-style-1便是黑色边框的表格，table-style-2便是黄色边框的表格。 <br/><br/>　　e) 表单修饰 form.css <br/><br/>　　定义fieldset、label、button、input 、sel&#101;ct、textarea这几个标签的表现。 <br/><br/>　　大多数网站的表单、按钮、输入框几乎都是一样的。之所以引入这个css，是为了便于统一在各个浏览器中的展现。默认的按钮、输入框等在各个浏览器下的展现区别很大，虽然在格式化的css中已经初步的统一，但是输入框的边框，按钮的样式都是需要在这个css中定义的。无奈的是sel&#101;ct无法做到统一，如果考虑到用js实现的话，这个成本太大了点。 <br/><br/>　　f) 打印修饰 print.css <br/><br/>　　修饰打印输出的页面。 <br/><br/>　　g) 包含其他css的css <br/><br/>　　frontpage.css、list.css、detail.css、register.css等等 <br/><br/>　　根据各种引用去引入相应的css。譬如list页面中没有需要表格的修饰，那就不引入table.css。以节约代码量。 <br/><br/>　　3、css框架文件夹的建立 <br/><br/>　　a) core 主要的 <br/><br/>　　存放reset.css、layout.css、type.css、print.css <br/><br/>　　b) bud 模块 <br/><br/>　　存放table.css、form.css、album.css等css <br/><br/>　　c) petal 具体应用 <br/><br/>　　存放封装过的css。frontpage.css、llist.css、detail.css、register.css等css。这个文件夹存放的css都是被直接引用的。 <br/><br/>　　文件夹的命名，按个人喜好啦! 我还希望用电子、质子等命名呢。嘿嘿！ <br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/188.htm</link>
			<title><![CDATA[深入浅出之正则表达式（二）]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Fri,07 Aug 2009 20:54:01 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=188</guid>
		<description><![CDATA[<p>&nbsp;</p>
<div style="margin: 0in 0in 0pt">前言：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本文是前一片文章<a href="http://dragon.cnblogs.com/archive/2006/05/08/394078.html"><font color="#000080">《深入浅出之正则表达式（一）》</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本文是Jan Goyvaerts为RegexBuddy写的教程的译文，版权归原作者所有，欢迎转载。但是为了尊重原作者和译者的劳动，请注明出处！谢谢！</a>的续篇，在本文中讲述了正则表达式中的组与向后引用，先前向后查看，条件测试，单词边界，选择符等表达式及例子，并分析了正则引擎在执行匹配时的内部机理。</div>
<div style="margin: 0in 0in 0pt"><b><span style="font-size: 18pt">&nbsp;<br />
</span></b></div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in">
<p style="margin: 0in 0in 0pt">&nbsp;</p>
</div>
<p><b><span>9.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>单词边界</b></p>
<div>&nbsp;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">元字符&lt;&lt;\b&gt;&gt;也是一种对位置进行匹配的&ldquo;锚&rdquo;。这种匹配是0长度匹配。</div>
<div style="margin: 0in 0in 0pt 0.25in">有4种位置被认为是&ldquo;单词边界&rdquo;：</div>
<div style="margin: 0in 0in 0pt 57pt; text-indent: -21pt"><span>1)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>在字符串的第一个字符前的位置(如果字符串的第一个字符是一个&ldquo;单词字符&rdquo;)</div>
<div style="margin: 0in 0in 0pt 57pt; text-indent: -21pt"><span>2)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>在字符串的最后一个字符后的位置(如果字符串的最后一个字符是一个&ldquo;单词字符&rdquo;)</div>
<div style="margin: 0in 0in 0pt 57pt; text-indent: -21pt"><span>3)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>在一个&ldquo;单词字符&rdquo;和&ldquo;非单词字符&rdquo;之间，其中&ldquo;非单词字符&rdquo;紧跟在&ldquo;单词字符&rdquo;之后</div>
<div style="margin: 0in 0in 0pt 57pt; text-indent: -21pt"><span>4)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>在一个&ldquo;非单词字符&rdquo;和&ldquo;单词字符&rdquo;之间，其中&ldquo;单词字符&rdquo;紧跟在&ldquo;非单词字符&rdquo;后面</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&nbsp;&ldquo;单词字符&rdquo;是可以用&ldquo;\w&rdquo;匹配的字符，&ldquo;非单词字符&rdquo;是可以用&ldquo;\W&rdquo;匹配的字符。在大多数的正则表达式实现中，&ldquo;单词字符&rdquo;通常包括&lt;&lt;[a-zA-Z0-9_]&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">例如：&lt;&lt;\b4\b&gt;&gt;能够匹配单个的4而不是一个更大数的一部分。这个正则表达式不会匹配&ldquo;44&rdquo;中的4。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">换种说法，几乎可以说&lt;&lt;\b&gt;&gt;匹配一个&ldquo;字母数字序列&rdquo;的开始和结束的位置。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&nbsp;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&ldquo;单词边界&rdquo;的取反集为&lt;&lt;\B&gt;&gt;，他要匹配的位置是两个&ldquo;单词字符&rdquo;之间或者两个&ldquo;非单词字符&rdquo;之间的位置。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>深入正则表达式引擎内部</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">让我们看看把正则表达式&lt;&lt;\bis\b&gt;&gt;应用到字符串&ldquo;This island is beautiful&rdquo;。引擎先处理符号&lt;&lt;\b&gt;&gt;。因为\b是0长度 ，所以第一个字符T前面的位置会被考察。因为T是一个&ldquo;单词字符&rdquo;，而它前面的字符是一个空字符(void)，所以\b匹配了单词边界。接着&lt;&lt;i&gt;&gt;和第一个字符&ldquo;T&rdquo;匹配失败。匹配过程继续进行，直到第五个空格符，和第四个字符&ldquo;s&rdquo;之间又匹配了&lt;&lt;\b&gt;&gt;。然而空格符和&lt;&lt;i&gt;&gt;不匹配。继续向后，到了第六个字符&ldquo;i&rdquo;，和第五个空格字符之间匹配了&lt;&lt;\b&gt;&gt;，然后&lt;&lt;is&gt;&gt;和第六、第七个字符都匹配了。然而第八个字符和第二个&ldquo;单词边界&rdquo;不匹配，所以匹配又失败了。到了第13个字符i，因为和前面一个空格符形成&ldquo;单词边界&rdquo;，同时&lt;&lt;is&gt;&gt;和&ldquo;is&rdquo;匹配。引擎接着尝试匹配第二个&lt;&lt;\b&gt;&gt;。因为第15个空格符和&ldquo;s&rdquo;形成单词边界，所以匹配成功。引擎&ldquo;急着&rdquo;返回成功匹配的结果。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>10.&nbsp;</span></b><b>选择符</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">正则表达式中&ldquo;|&rdquo;表示选择。你可以用选择符匹配多个可能的正则表达式中的一个。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">如果你想搜索文字&ldquo;cat&rdquo;或&ldquo;dog&rdquo;，你可以用&lt;&lt;cat|dog&gt;&gt;。如果你想有更多的选择，你只要扩展列表&lt;&lt;cat|dog|mouse|fish&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">选择符在正则表达式中具有最低的优先级，也就是说，它告诉引擎要么匹配选择符左边的所有表达式，要么匹配右边的所有表达式。你也可以用圆括号来限制选择符的作用范围。如&lt;&lt;\b(cat|dog)\b&gt;&gt;，这样告诉正则引擎把(cat|dog)当成一个正则表达式单位来处理。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>注意正则引擎的&ldquo;急于表功&rdquo;性</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">正则引擎是急切的，当它找到一个有效的匹配时，它会停止搜索。因此在一定条件下，选择符两边的表达式的顺序对结果会有影响。假设你想用正则表达式搜索一个编程语言的函数列表：Get，GetValue，Set或SetValue。一个明显的解决方案是&lt;&lt;Get|GetValue|Set|SetValue&gt;&gt;。让我们看看当搜索SetValue时的结果。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">因为&lt;&lt;Get&gt;&gt;和&lt;&lt;GetValue&gt;&gt;都失败了，而&lt;&lt;Set&gt;&gt;匹配成功。因为正则导向的引擎都是&ldquo;急切&rdquo;的，所以它会返回第一个成功的匹配，就是&ldquo;Set&rdquo;，而不去继续搜索是否有其他更好的匹配。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">和我们期望的相反，正则表达式并没有匹配整个字符串。有几种可能的解决办法。一是考虑到正则引擎的&ldquo;急切&rdquo;性，改变选项的顺序，例如我们使用&lt;&lt;GetValue|Get|SetValue|Set&gt;&gt;，这样我们就可以优先搜索最长的匹配。我们也可以把四个选项结合起来成两个选项：&lt;&lt;Get(Value)?|Set(Value)?&gt;&gt;。因为问号重复符是贪婪的，所以SetValue总会在Set之前被匹配。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">一个更好的方案是使用单词边界：&lt;&lt;\b(Get|GetValue|Set|SetValue)\b&gt;&gt;或&lt;&lt;\b(Get(Value)?|Set(Value)?\b&gt;&gt;。更进一步，既然所有的选择都有相同的结尾，我们可以把正则表达式优化为&lt;&lt;\b(Get|Set)(Value)?\b&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>11.&nbsp;</span></b><b>组与向后引用</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">把正则表达式的一部分放在圆括号内，你可以将它们形成组。然后你可以对整个组使用一些正则操作，例如重复操作符。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">要注意的是，只有圆括号&ldquo;()&rdquo;才能用于形成组。&ldquo;[]&rdquo;用于定义字符集。&ldquo;{}&rdquo;用于定义重复操作。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">当用&ldquo;()&rdquo;定义了一个正则表达式组后，正则引擎则会把被匹配的组按照顺序编号，存入缓存。当对被匹配的组进行向后引用的时候，可以用&ldquo;\数字&rdquo;的方式进行引用。&lt;&lt;\1&gt;&gt;引用第一个匹配的后向引用组，&lt;&lt;\2&gt;&gt;引用第二个组，以此类推，&lt;&lt;\n&gt;&gt;引用第n个组。而&lt;&lt;\0&gt;&gt;则引用整个被匹配的正则表达式本身。我们看一个例子。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">假设你想匹配一个HTML标签的开始标签和结束标签，以及标签中间的文本。比如&lt;B&gt;This is a test&lt;/B&gt;，我们要匹配&lt;B&gt;和&lt;/B&gt;以及中间的文字。我们可以用如下正则表达式：&ldquo;&lt;([A-Z][A-Z0-9]*)[^&gt;]*&gt;.*?&lt;/\1&gt;&rdquo;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">首先，&ldquo;&lt;&rdquo;将会匹配&ldquo;&lt;B&gt;&rdquo;的第一个字符&ldquo;&lt;&rdquo;。然后[A-Z]匹配B，[A-Z0-9]*将会匹配0到多次字母数字，后面紧接着0到多个非&ldquo;&gt;&rdquo;的字符。最后正则表达式的&ldquo;&gt;&rdquo;将会匹配&ldquo;&lt;B&gt;&rdquo;的&ldquo;&gt;&rdquo;。接下来正则引擎将对结束标签之前的字符进行惰性匹配，直到遇到一个&ldquo;&lt;/&rdquo;符号。然后正则表达式中的&ldquo;\1&rdquo;表示对前面匹配的组&ldquo;([A-Z][A-Z0-9]*)&rdquo;进行引用，在本例中，被引用的是标签名&ldquo;B&rdquo;。所以需要被匹配的结尾标签为&ldquo;&lt;/B&gt;&rdquo;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">你可以对相同的后向引用组进行多次引用，&lt;&lt;([a-c])x\1x\1&gt;&gt;将匹配&ldquo;axaxa&rdquo;、&ldquo;bxbxb&rdquo;以及&ldquo;cxcxc&rdquo;。如果用数字形式引用的组没有有效的匹配，则引用到的内容简单的为空。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">一个后向引用不能用于它自身。&lt;&lt;([abc]\1)&gt;&gt;是错误的。因此你不能将&lt;&lt;\0&gt;&gt;用于一个正则表达式匹配本身，它只能用于替换操作中。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">后向引用不能用于字符集内部。&lt;&lt;(a)[\1b]&gt;&gt;中的&lt;&lt;\1&gt;&gt;并不表示后向引用。在字符集内部，&lt;&lt;\1&gt;&gt;可以被解释为八进制形式的转码。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">向后引用会降低引擎的速度，因为它需要存储匹配的组。如果你不需要向后引用，你可以告诉引擎对某个组不存储。例如：&lt;&lt;Get(?:Value)&gt;&gt;。其中&ldquo;(&rdquo;后面紧跟的&ldquo;?:&rdquo;会告诉引擎对于组(Value)，不存储匹配的值以供后向引用。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>重复操作与后向引用</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">当对组使用重复操作符时，缓存里后向引用内容会被不断刷新，只保留最后匹配的内容。例如：&lt;&lt;([abc]+)=\1&gt;&gt;将匹配&ldquo;cab=cab&rdquo;，但是&lt;&lt;([abc])+=\1&gt;&gt;却不会。因为([abc])第一次匹配&ldquo;c&rdquo;时，&ldquo;\1&rdquo;代表&ldquo;c&rdquo;；然后([abc])会继续匹配&ldquo;a&rdquo;和&ldquo;b&rdquo;。最后&ldquo;\1&rdquo;代表&ldquo;b&rdquo;，所以它会匹配&ldquo;cab=b&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">应用：检查重复单词--当编辑文字时，很容易就会输入重复单词，例如&ldquo;the the&rdquo;。使用&lt;&lt;\b(\w+)\s+\1\b&gt;&gt;可以检测到这些重复单词。要删除第二个单词，只要简单的利用替换功能替换掉&ldquo;\1&rdquo;就可以了。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>组的命名和引用</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">在PHP，Python中，可以用&lt;&lt;(?P&lt;name&gt;group)&gt;&gt;来对组进行命名。在本例中，词法?P&lt;name&gt;就是对组(group)进行了命名。其中name是你对组的起的名字。你可以用(?P=name)进行引用。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">.NET的命名组</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">.NET framework也支持命名组。不幸的是，微软的程序员们决定发明他们自己的语法，而不是沿用Perl、Python的规则。目前为止，还没有任何其他的正则表达式实现支持微软发明的语法。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">下面是.NET中的例子：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">(?&lt;first&gt;group)(?&rsquo;second&rsquo;group)</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">正如你所看到的，.NET提供两种词法来创建命名组：一是用尖括号&ldquo;&lt;&gt;&rdquo;，或者用单引号&ldquo;&rsquo;&rsquo;&rdquo;。尖括号在字符串中使用更方便，单引号在ASP代码中更有用，因为ASP代码中&ldquo;&lt;&gt;&rdquo;被用作HTML标签。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">要引用一个命名组，使用\k&lt;name&gt;或\k&rsquo;name&rsquo;.</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">当进行搜索替换时，你可以用&ldquo;${name}&rdquo;来引用一个命名组。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>12.&nbsp;</span></b><b>正则表达式的匹配模式</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">本教程所讨论的正则表达式引擎都支持三种匹配模式：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&lt;&lt;/i&gt;&gt;使正则表达式对大小写不敏感，</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&lt;&lt;/s&gt;&gt;开启&ldquo;单行模式&rdquo;，即点号&ldquo;.&rdquo;匹配新行符</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&lt;&lt;/m&gt;&gt;开启&ldquo;多行模式&rdquo;，即&ldquo;^&rdquo;和&ldquo;$&rdquo;匹配新行符的前面和后面的位置。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>在正则表达式内部打开或关闭模式</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如果你在正则表达式内部插入修饰符(?ism)，则该修饰符只对其右边的正则表达式起作用。(?-i)是关闭大小写不敏感。你可以很快的进行测试。&lt;&lt;(?i)te(?-i)st&gt;&gt;应该匹配TEst，但是不能匹配teST或TEST.</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>13.&nbsp;</span></b><b>原子组与防止回溯</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">在一些特殊情况下，因为回溯会使得引擎的效率极其低下。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">让我们看一个例子：要匹配这样的字串，字串中的每个字段间用逗号做分隔符，第12个字段由P开头。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">我们容易想到这样的正则表达式&lt;&lt;^(.*?,){11}P&gt;&gt;。这个正则表达式在正常情况下工作的很好。但是在极端情况下，如果第12个字段不是由P开头，则会发生灾难性的回溯。如要搜索的字串为&ldquo;1,2,3,4,5,6,7,8,9,10,11,12,13&rdquo;。首先，正则表达式一直成功匹配直到第12个字符。这时，前面的正则表达式消耗的字串为&ldquo;1,2,3,4,5,6,7,8,9,10,11,&rdquo;，到了下一个字符，&lt;&lt;P&gt;&gt;并不匹配&ldquo;12&rdquo;。所以引擎进行回溯，这时正则表达式消耗的字串为&ldquo;1,2,3,4,5,6,7,8,9,10,11&rdquo;。继续下一次匹配过程，下一个正则符号为点号&lt;&lt;.&gt;&gt;，可以匹配下一个逗号&ldquo;,&rdquo;。然而&lt;&lt;，&gt;&gt;并不匹配字符&ldquo;12&rdquo;中的&ldquo;1&rdquo;。匹配失败，继续回溯。大家可以想象，这样的回溯组合是个非常大的数量。因此可能会造成引擎崩溃。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">用于阻止这样巨大的回溯有几种方案：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">一种简单的方案是尽可能的使匹配精确。用取反字符集代替点号。例如我们用如下正则表达式&lt;&lt;^([^,\r\n]*,){11}P&gt;&gt;，这样可以使失败回溯的次数下降到11次。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">另一种方案是使用原子组。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">原子组的目的是使正则引擎失败的更快一点。因此可以有效的阻止海量回溯。原子组的语法是&lt;&lt;(?&gt;正则表达式)&gt;&gt;。位于(?&gt;)之间的所有正则表达式都会被认为是一个单一的正则符号。一旦匹配失败，引擎将会回溯到原子组前面的正则表达式部分。前面的例子用原子组可以表达成&lt;&lt;^(?&gt;(.*?,){11})P&gt;&gt;。一旦第十二个字段匹配失败，引擎回溯到原子组前面的&lt;&lt;^&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>14.&nbsp;</span></b><b>向前查看与向后查看</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">Perl 5 引入了两个强大的正则语法：&ldquo;向前查看&rdquo;和&ldquo;向后查看&rdquo;。他们也被称作&ldquo;零长度断言&rdquo;。他们和锚定一样都是零长度的（所谓零长度即指该正则表达式不消耗被匹配的字符串）。不同之处在于&ldquo;前后查看&rdquo;会实际匹配字符，只是他们会抛弃匹配只返回匹配结果：匹配或不匹配。这就是为什么他们被称作&ldquo;断言&rdquo;。他们并不实际消耗字符串中的字符，而只是断言一个匹配是否可能。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">几乎本文讨论的所有正则表达式的实现都支持&ldquo;向前向后查看&rdquo;。唯一的一个例外是Javascript只支持向前查看。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>肯定和否定式的向前查看</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如我们前面提过的一个例子：要查找一个q，后面没有紧跟一个u。也就是说，要么q后面没有字符，要么后面的字符不是u。采用否定式向前查看后的一个解决方案为&lt;&lt;q(?!u)&gt;&gt;。否定式向前查看的语法是&lt;&lt;(?!查看的内容)&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">肯定式向前查看和否定式向前查看很类似：&lt;&lt;(?=查看的内容)&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如果在&ldquo;查看的内容&rdquo;部分有组，也会产生一个向后引用。但是向前查看本身并不会产生向后引用，也不会被计入向后引用的编号中。这是因为向前查看本身是会被抛弃掉的，只保留匹配与否的判断结果。如果你想保留匹配的结果作为向后引用，你可以用&lt;&lt;(?=(regex))&gt;&gt;来产生一个向后引用。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>肯定和否定式的先后查看</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">向后查看和向前查看有相同的效果，只是方向相反</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">否定式向后查看的语法是：&lt;&lt;(?&lt;!查看内容)&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">肯定式向后查看的语法是：&lt;&lt;(?&lt;=查看内容)&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">我们可以看到，和向前查看相比，多了一个表示方向的左尖括号。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">例：&lt;&lt;(?&lt;!a)b&gt;&gt;将会匹配一个没有&ldquo;a&rdquo;作前导字符的&ldquo;b&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">值得注意的是：向前查看从当前字符串位置开始对&ldquo;查看&rdquo;正则表达式进行匹配；向后查看则从当前字符串位置开始先后回溯一个字符，然后再开始对&ldquo;查看&rdquo;正则表达式进行匹配。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>深入正则表达式引擎内部</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">让我们看一个简单例子。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">把正则表达式&lt;&lt;q(?!u)&gt;&gt;应用到字符串&ldquo;Iraq&rdquo;。正则表达式的第一个符号是&lt;&lt;q&gt;&gt;。正如我们知道的，引擎在匹配&lt;&lt;q&gt;&gt;以前会扫过整个字符串。当第四个字符&ldquo;q&rdquo;被匹配后，&ldquo;q&rdquo;后面是空字符(void)。而下一个正则符号是向前查看。引擎注意到已经进入了一个向前查看正则表达式部分。下一个正则符号是&lt;&lt;u&gt;&gt;，和空字符不匹配，从而导致向前查看里的正则表达式匹配失败。因为是一个否定式的向前查看，意味着整个向前查看结果是成功的。于是匹配结果&ldquo;q&rdquo;被返回了。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">我们在把相同的正则表达式应用到&ldquo;quit&rdquo;。&lt;&lt;q&gt;&gt;匹配了&ldquo;q&rdquo;。下一个正则符号是向前查看部分的&lt;&lt;u&gt;&gt;，它匹配了字符串中的第二个字符&ldquo;i&rdquo;。引擎继续走到下个字符&ldquo;i&rdquo;。然而引擎这时注意到向前查看部分已经处理完了，并且向前查看已经成功。于是引擎抛弃被匹配的字符串部分，这将导致引擎回退到字符&ldquo;u&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">因为向前查看是否定式的，意味着查看部分的成功匹配导致了整个向前查看的失败，因此引擎不得不进行回溯。最后因为再没有其他的&ldquo;q&rdquo;和&lt;&lt;q&gt;&gt;匹配，所以整个匹配失败了。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">为了确保你能清楚地理解向前查看的实现，让我们把&lt;&lt;q(?=u)i&gt;&gt;应用到&ldquo;quit&rdquo;。&lt;&lt;q&gt;&gt;首先匹配&ldquo;q&rdquo;。然后向前查看成功匹配&ldquo;u&rdquo;，匹配的部分被抛弃，只返回可以匹配的判断结果。引擎从字符&ldquo;i&rdquo;回退到&ldquo;u&rdquo;。由于向前查看成功了，引擎继续处理下一个正则符号&lt;&lt;i&gt;&gt;。结果发现&lt;&lt;i&gt;&gt;和&ldquo;u&rdquo;不匹配。因此匹配失败了。由于后面没有其他的&ldquo;q&rdquo;，整个正则表达式的匹配失败了。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>更进一步理解正则表达式引擎内部机制</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">让我们把&lt;&lt;(?&lt;=a)b&gt;&gt;应用到&ldquo;thingamabob&rdquo;。引擎开始处理向后查看部分的正则符号和字符串中的第一个字符。在这个例子中，向后查看告诉正则表达式引擎回退一个字符，然后查看是否有一个&ldquo;a&rdquo;被匹配。因为在&ldquo;t&rdquo;前面没有字符，所以引擎不能回退。因此向后查看失败了。引擎继续走到下一个字符&ldquo;h&rdquo;。再一次，引擎暂时回退一个字符并检查是否有个&ldquo;a&rdquo;被匹配。结果发现了一个&ldquo;t&rdquo;。向后查看又失败了。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">向后查看继续失败，直到正则表达式到达了字符串中的&ldquo;m&rdquo;，于是肯定式的向后查看被匹配了。因为它是零长度的，字符串的当前位置仍然是&ldquo;m&rdquo;。下一个正则符号是&lt;&lt;b&gt;&gt;，和&ldquo;m&rdquo;匹配失败。下一个字符是字符串中的第二个&ldquo;a&rdquo;。引擎向后暂时回退一个字符，并且发现&lt;&lt;a&gt;&gt;不匹配&ldquo;m&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">在下一个字符是字符串中的第一个&ldquo;b&rdquo;。引擎暂时性的向后退一个字符发现向后查看被满足了，同时&lt;&lt;b&gt;&gt;匹配了&ldquo;b&rdquo;。因此整个正则表达式被匹配了。作为结果，正则表达式返回字符串中的第一个&ldquo;b&rdquo;。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>向前向后查看的应用</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">我们来看这样一个例子：查找一个具有6位字符的，含有&ldquo;cat&rdquo;的单词。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">首先，我们可以不用向前向后查看来解决问题，例如：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.5in">&lt;&lt; cat\w{3}|\wcat\w{2}|\w{2}cat\w|\w{3}cat&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">足够简单吧！但是当需求变成查找一个具有6-12位字符，含有&ldquo;cat&rdquo;，&ldquo;dog&rdquo;或&ldquo;mouse&rdquo;的单词时，这种方法就变得有些笨拙了。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">我们来看看使用向前查看的方案。在这个例子中，我们有两个基本需求要满足：一是我们需要一个6位的字符，二是单词含有&ldquo;cat&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">满足第一个需求的正则表达式为&lt;&lt;\b\w{6}\b&gt;&gt;。满足第二个需求的正则表达式为&lt;&lt;\b\w*cat\w*\b&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">把两者结合起来，我们可以得到如下的正则表达式：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;&nbsp;&nbsp;&nbsp; &lt;&lt;(?=\b\w{6}\b)\b\w*cat\w*\b&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">具体的匹配过程留给读者。但是要注意的一点是，向前查看是不消耗字符的，因此当判断单词满足具有6个字符的条件后，引擎会从开始判断前的位置继续对后面的正则表达式进行匹配。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">最后作些优化，可以得到下面的正则表达式：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\b(?=\w{6}\b)\w{0,3}cat\w*&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>15.&nbsp;</span></b><b>正则表达式中的条件测试</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">条件测试的语法为&lt;&lt;(?ifthen|else)&gt;&gt;。&ldquo;if&rdquo;部分可以是向前向后查看表达式。如果用向前查看，则语法变为：&lt;&lt;(?(?=regex)then|else)&gt;&gt;，其中else部分是可选的。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">如果if部分为true，则正则引擎会试图匹配then部分，否则引擎会试图匹配else部分。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">需要记住的是，向前先后查看并不实际消耗任何字符，因此后面的then与else部分的匹配时从if测试前的部分开始进行尝试。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>16.&nbsp;</span></b><b>为正则表达式添加注释</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">在正则表达式中添加注释的语法是：&lt;&lt;(?#comment)&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">例：为用于匹配有效日期的正则表达式添加注释：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&nbsp;(?#year)(19|20)\d\d[- /.](?#month)(0[1-9]|1[012])[- /.](?#day)(0[1-9]|[12][0-9]|3[01])</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/187.htm</link>
			<title><![CDATA[深入浅出之正则表达式（一）]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Fri,07 Aug 2009 20:52:23 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=187</guid>
		<description><![CDATA[<p>前言：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;半年前我对正则表达式产生了兴趣，在网上查找过不少资料，看过不少的教程，最后在使用一个正则表达式工具RegexBuddy时发现他的教程写的非常好，可以说是我目前见过最好的正则表达式教程。于是一直想把他翻译过来。这个愿望直到这个五一长假才得以实现，结果就有了这篇文章。关于本文的名字，使用&ldquo;深入浅出&rdquo;似乎已经太俗。但是通读原文以后，觉得只有用&ldquo;深入浅出&rdquo;才能准确的表达出该教程给我的感受，所以也就不能免俗了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本文是Jan Goyvaerts为RegexBuddy写的教程的译文，版权归原作者所有，欢迎转载。但是为了尊重原作者和译者的劳动，请注明出处！谢谢！</p>
<div style="margin: 0in 0in 0pt"><b><span style="font-size: 18pt">&nbsp;</span></b></div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>什么是正则表达式</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">基本说来，正则表达式是一种用来描述一定数量文本的模式。Regex代表Regular Express。本文将用&lt;&lt;regex&gt;&gt;来表示一段具体的正则表达式。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">一段文本就是最基本的模式，简单的匹配相同的文本。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>不同的正则表达式引擎</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">正则表达式引擎是一种可以处理正则表达式的软件。通常，引擎是更大的应用程序的一部分。在软件世界，不同的正则表达式并不互相兼容。本教程会集中讨论Perl 5 类型的引擎，因为这种引擎是应用最广泛的引擎。同时我们也会提到一些和其他引擎的区别。许多近代的引擎都很类似，但不完全一样。例如.NET正则库，JDK正则包。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>文字符号</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">最基本的正则表达式由单个文字符号组成。如&lt;&lt;a&gt;&gt;，它将匹配字符串中第一次出现的字符&ldquo;a&rdquo;。如对字符串&ldquo;Jack is a boy&rdquo;。&ldquo;J&rdquo;后的&ldquo;a&rdquo;将被匹配。而第二个&ldquo;a&rdquo;将不会被匹配。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">正则表达式也可以匹配第二个&ldquo;a&rdquo;，这必须是你告诉正则表达式引擎从第一次匹配的地方开始搜索。在文本编辑器中，你可以使用&ldquo;查找下一个&rdquo;。在编程语言中，会有一个函数可以使你从前一次匹配的位置开始继续向后搜索。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">类似的，&lt;&lt;cat&gt;&gt;会匹配&ldquo;About cats and dogs&rdquo;中的&ldquo;cat&rdquo;。这等于是告诉正则表达式引擎，找到一个&lt;&lt;c&gt;&gt;，紧跟一个&lt;&lt;a&gt;&gt;，再跟一个&lt;&lt;t&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">要注意，正则表达式引擎缺省是大小写敏感的。除非你告诉引擎忽略大小写，否则&lt;&lt;cat&gt;&gt;不会匹配&ldquo;Cat&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>特殊字符</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">对于文字字符，有11个字符被保留作特殊用途。他们是：</div>
<div style="margin: 0in 0in 0pt 0.5in; text-indent: 0.5in">[ ] \ ^ $ . | ? * + ( )</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">这些特殊字符也被称作元字符。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如果你想在正则表达式中将这些字符用作文本字符，你需要用反斜杠&ldquo;\&rdquo;对其进行换码 (escape)。例如你想匹配&ldquo;1+1=2&rdquo;，正确的表达式为&lt;&lt;1\+1=2&gt;&gt;.</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">需要注意的是，&lt;&lt;1+1=2&gt;&gt;也是有效的正则表达式。但它不会匹配&ldquo;1+1=2&rdquo;，而会匹配&ldquo;123+111=234&rdquo;中的&ldquo;111=2&rdquo;。因为&ldquo;+&rdquo;在这里表示特殊含义（重复1次到多次）。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">在编程语言中，要注意，一些特殊的字符会先被编译器处理，然后再传递给正则引擎。因此正则表达式&lt;&lt;1\+2=2&gt;&gt;在C++中要写成&ldquo;1\\+1=2&rdquo;。为了匹配&ldquo;C:\temp&rdquo;，你要用正则表达式&lt;&lt;C:\\temp&gt;&gt;。而在C++中，正则表达式则变成了&ldquo;C:\\\\temp&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>不可显示字符</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">可以使用特殊字符序列来代表某些不可显示字符：</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\t&gt;&gt;代表Tab(0x09)</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\r&gt;&gt;代表回车符(0x0D)</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\n&gt;&gt;代表换行符(0x0A)</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">要注意的是Windows中文本文件使用&ldquo;\r\n&rdquo;来结束一行而Unix使用&ldquo;\n&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>正则表达式引擎的内部工作机制</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">知道正则表达式引擎是如何工作的有助于你很快理解为何某个正则表达式不像你期望的那样工作。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">有两种类型的引擎：文本导向(text-directed)的引擎和正则导向(regex-directed)的引擎。Jeffrey Friedl把他们称作DFA和NFA引擎。本文谈到的是正则导向的引擎。这是因为一些非常有用的特性，如&ldquo;惰性&rdquo;量词(lazy quantifiers)和反向引用(backreferences)，只能在正则导向的引擎中实现。所以毫不意外这种引擎是目前最流行的引擎。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">你可以轻易分辨出所使用的引擎是文本导向还是正则导向。如果反向引用或&ldquo;惰性&rdquo;量词被实现，则可以肯定你使用的引擎是正则导向的。你可以作如下测试：将正则表达式&lt;&lt;regex|regex not&gt;&gt;应用到字符串&ldquo;regex not&rdquo;。如果匹配的结果是regex，则引擎是正则导向的。如果结果是regex not，则是文本导向的。因为正则导向的引擎是&ldquo;猴急&rdquo;的，它会很急切的进行表功，报告它找到的第一个匹配 。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>正则导向的引擎总是返回最左边的匹配</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">这是需要你理解的很重要的一点：即使以后有可能发现一个&ldquo;更好&rdquo;的匹配，正则导向的引擎也总是返回最左边的匹配。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">当把&lt;&lt;cat&gt;&gt;应用到&ldquo;He captured a catfish for his cat&rdquo;，引擎先比较&lt;&lt;c&gt;&gt;和&ldquo;H&rdquo;，结果失败了。于是引擎再比较&lt;&lt;c&gt;&gt;和&ldquo;e&rdquo;，也失败了。直到第四个字符，&lt;&lt;c&gt;&gt;匹配了&ldquo;c&rdquo;。&lt;&lt;a&gt;&gt;匹配了第五个字符。到第六个字符&lt;&lt;t&gt;&gt;没能匹配&ldquo;p&rdquo;，也失败了。引擎再继续从第五个字符重新检查匹配性。直到第十五个字符开始，&lt;&lt;cat&gt;&gt;匹配上了&ldquo;catfish&rdquo;中的&ldquo;cat&rdquo;，正则表达式引擎急切的返回第一个匹配的结果，而不会再继续查找是否有其他更好的匹配。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>字符集</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">字符集是由一对方括号&ldquo;[]&rdquo;括起来的字符集合。使用字符集，你可以告诉正则表达式引擎仅仅匹配多个字符中的一个。如果你想匹配一个&ldquo;a&rdquo;或一个&ldquo;e&rdquo;，使用&lt;&lt;[ae]&gt;&gt;。你可以使用&lt;&lt;gr[ae]y&gt;&gt;匹配gray或grey。这在你不确定你要搜索的字符是采用美国英语还是英国英语时特别有用。相反，&lt;&lt;gr[ae]y&gt;&gt;将不会匹配graay或graey。字符集中的字符顺序并没有什么关系，结果都是相同的。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">你可以使用连字符&ldquo;-&rdquo;定义一个字符范围作为字符集。&lt;&lt;[0-9]&gt;&gt;匹配0到9之间的单个数字。你可以使用不止一个范围。&lt;&lt;[0-9a-fA-F] &gt;&gt;匹配单个的十六进制数字，并且大小写不敏感。你也可以结合范围定义与单个字符定义。&lt;&lt;[0-9a-fxA-FX]&gt;&gt;匹配一个十六进制数字或字母X。再次强调一下，字符和范围定义的先后顺序对结果没有影响。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>字符集的一些应用</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">查找一个可能有拼写错误的单词，比如&lt;&lt;sep[ae]r[ae]te&gt;&gt; 或 &lt;&lt;li[cs]en[cs]e&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">查找程序语言的标识符，&lt;&lt;A-Za-z_][A-Za-z_0-9]*&gt;&gt;。(*表示重复0或多次)</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">查找C风格的十六进制数&lt;&lt;0[xX][A-Fa-f0-9]+&gt;&gt;。(+表示重复一次或多次)</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>取反字符集</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">在左方括号&ldquo;[&rdquo;后面紧跟一个尖括号&ldquo;^&rdquo;，将会对字符集取反。结果是字符集将匹配任何不在方括号中的字符。不像&ldquo;.&rdquo;，取反字符集是可以匹配回车换行符的。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">需要记住的很重要的一点是，取反字符集必须要匹配一个字符。&lt;&lt;q[^u]&gt;&gt;并不意味着：匹配一个q，后面没有u跟着。它意味着：匹配一个q，后面跟着一个不是u的字符。所以它不会匹配&ldquo;Iraq&rdquo;中的q，而会匹配&ldquo;Iraq is a country&rdquo;中的q和一个空格符。事实上，空格符是匹配中的一部分，因为它是一个&ldquo;不是u的字符&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如果你只想匹配一个q，条件是q后面有一个不是u的字符，我们可以用后面将讲到的向前查看来解决。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>字符集中的元字符</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">需要注意的是，在字符集中只有4个 字符具有特殊含义。它们是：&ldquo;] \ ^ -&rdquo;。&ldquo;]&rdquo;代表字符集定义的结束；&ldquo;\&rdquo;代表转义；&ldquo;^&rdquo;代表取反；&ldquo;-&rdquo;代表范围定义。其他常见的元字符在字符集定义内部都是正常字符，不需要转义。例如，要搜索星号*或加号+，你可以用&lt;&lt;[+*]&gt;&gt;。当然，如果你对那些通常的元字符进行转义，你的正则表达式一样会工作得很好，但是这会降低可读性。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">在字符集定义中为了将反斜杠&ldquo;\&rdquo;作为一个文字字符而非特殊含义的字符，你需要用另一个反斜杠对它进行转义。&lt;&lt;[\\x]&gt;&gt;将会匹配一个反斜杠和一个X。&ldquo;]^-&rdquo;都可以用反斜杠进行转义，或者将他们放在一个不可能使用到他们特殊含义的位置。我们推荐后者，因为这样可以增加可读性。比如对于字符&ldquo;^&rdquo;，将它放在除了左括号&ldquo;[&rdquo;后面的位置，使用的都是文字字符含义而非取反含义。如&lt;&lt;[x^]&gt;&gt;会匹配一个x或^。&lt;&lt;[]x]&gt;&gt;会匹配一个&ldquo;]&rdquo;或&ldquo;x&rdquo;。&lt;&lt;[-x]&gt;&gt;或&lt;&lt;[x-]&gt;&gt;都会匹配一个&ldquo;-&rdquo;或&ldquo;x&rdquo;。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>字符集的简写</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">因为一些字符集非常常用，所以有一些简写方式。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\d&gt;&gt;代表&lt;&lt;[0-9]&gt;&gt;;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\w&gt;&gt;代表单词字符。这个是随正则表达式实现的不同而有些差异。绝大多数的正则表达式实现的单词字符集都包含了&lt;&lt;A-Za-z0-9_]&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\s&gt;&gt;代表&ldquo;白字符&rdquo;。这个也是和不同的实现有关的。在绝大多数的实现中，都包含了空格符和Tab符，以及回车换行符&lt;&lt;\r\n&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">字符集的缩写形式可以用在方括号之内或之外。&lt;&lt;\s\d&gt;&gt;匹配一个白字符后面紧跟一个数字。&lt;&lt;[\s\d]&gt;&gt;匹配单个白字符或数字。&lt;&lt;[\da-fA-F]&gt;&gt;将匹配一个十六进制数字。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">取反字符集的简写</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;[\S]&gt;&gt; = &lt;&lt;[^\s]&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;[\W]&gt;&gt; = &lt;&lt;[^\w]&gt;&gt;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;[\D]&gt;&gt; = &lt;&lt;[^\d]&gt;&gt;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>字符集的重复</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如果你用&ldquo;?*+&rdquo;操作符来重复一个字符集，你将会重复整个字符集。而不仅是它匹配的那个字符。正则表达式&lt;&lt;[0-9]+&gt;&gt;会匹配837以及222。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如果你仅仅想重复被匹配的那个字符，可以用向后引用达到目的。我们以后将讲到向后引用。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>使用?*</b><b>或+ </b><b>进行重复</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">?：告诉引擎匹配前导字符0次或一次。事实上是表示前导字符是可选的。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">+：告诉引擎匹配前导字符1次或多次</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">*：告诉引擎匹配前导字符0次或多次</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&lt;[A-Za-z][A-Za-z0-9]*&gt;匹配没有属性的HTML标签，&ldquo;&lt;&rdquo;以及&ldquo;&gt;&rdquo;是文字符号。第一个字符集匹配一个字母，第二个字符集匹配一个字母或数字。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">我们似乎也可以用&lt;[A-Za-z0-9]+&gt;。但是它会匹配&lt;1&gt;。但是这个正则表达式在你知道你要搜索的字符串不包含类似的无效标签时还是足够有效的。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>限制性重复</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">许多现代的正则表达式实现，都允许你定义对一个字符重复多少次。词法是：{min,max}。min和max都是非负整数。如果逗号有而max被忽略了，则max没有限制。如果逗号和max都被忽略了，则重复min次。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">因此{0,}和*一样，{1，}和+ 的作用一样。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">你可以用&lt;&lt;\b[1-9][0-9]{3}\b&gt;&gt;匹配1000~9999之间的数字(&ldquo;\b&rdquo;表示单词边界)。&lt;&lt;\b[1-9][0-9]{2,4}\b&gt;&gt;匹配一个在100~99999之间的数字。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>注意贪婪性</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">假设你想用一个正则表达式匹配一个HTML标签。你知道输入将会是一个有效的HTML文件，因此正则表达式不需要排除那些无效的标签。所以如果是在两个尖括号之间的内容，就应该是一个HTML标签。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">许多正则表达式的新手会首先想到用正则表达式&lt;&lt; &lt;.+&gt; &gt;&gt;，他们会很惊讶的发现，对于测试字符串，&ldquo;This is a &lt;EM&gt;first&lt;/EM&gt; test&rdquo;，你可能期望会返回&lt;EM&gt;，然后继续进行匹配的时候，返回&lt;/EM&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">但事实是不会。正则表达式将会匹配&ldquo;&lt;EM&gt;first&lt;/EM&gt;&rdquo;。很显然这不是我们想要的结果。原因在于&ldquo;+&rdquo;是贪婪的。也就是说，&ldquo;+&rdquo;会导致正则表达式引擎试图尽可能的重复前导字符。只有当这种重复会引起整个正则表达式匹配失败的情况下，引擎会进行回溯。也就是说，它会放弃最后一次的&ldquo;重复&rdquo;，然后处理正则表达式余下的部分。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">和&ldquo;+&rdquo;类似，&ldquo;?*&rdquo;的重复也是贪婪的。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>深入正则表达式引擎内部</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">让我们来看看正则引擎如何匹配前面的例子。第一个记号是&ldquo;&lt;&rdquo;，这是一个文字符号。第二个符号是&ldquo;.&rdquo;，匹配了字符&ldquo;E&rdquo;，然后&ldquo;+&rdquo;一直可以匹配其余的字符，直到一行的结束。然后到了换行符，匹配失败(&ldquo;.&rdquo;不匹配换行符)。于是引擎开始对下一个正则表达式符号进行匹配。也即试图匹配&ldquo;&gt;&rdquo;。到目前为止，&ldquo;&lt;.+&rdquo;已经匹配了&ldquo;&lt;EM&gt;first&lt;/EM&gt; test&rdquo;。引擎会试图将&ldquo;&gt;&rdquo;与换行符进行匹配，结果失败了。于是引擎进行回溯。结果是现在&ldquo;&lt;.+&rdquo;匹配&ldquo;&lt;EM&gt;first&lt;/EM&gt; tes&rdquo;。于是引擎将&ldquo;&gt;&rdquo;与&ldquo;t&rdquo;进行匹配。显然还是会失败。这个过程继续，直到&ldquo;&lt;.+&rdquo;匹配&ldquo;&lt;EM&gt;first&lt;/EM&rdquo;，&ldquo;&gt;&rdquo;与&ldquo;&gt;&rdquo;匹配。于是引擎找到了一个匹配&ldquo;&lt;EM&gt;first&lt;/EM&gt;&rdquo;。记住，正则导向的引擎是&ldquo;急切的&rdquo;，所以它会急着报告它找到的第一个匹配。而不是继续回溯，即使可能会有更好的匹配，例如&ldquo;&lt;EM&gt;&rdquo;。所以我们可以看到，由于&ldquo;+&rdquo;的贪婪性，使得正则表达式引擎返回了一个最左边的最长的匹配。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>用懒惰性取代贪婪性</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">一个用于修正以上问题的可能方案是用&ldquo;+&rdquo;的惰性代替贪婪性。你可以在&ldquo;+&rdquo;后面紧跟一个问号&ldquo;?&rdquo;来达到这一点。&ldquo;*&rdquo;，&ldquo;{}&rdquo;和&ldquo;?&rdquo;表示的重复也可以用这个方案。因此在上面的例子中我们可以使用&ldquo;&lt;.+?&gt;&rdquo;。让我们再来看看正则表达式引擎的处理过程。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">再一次，正则表达式记号&ldquo;&lt;&rdquo;会匹配字符串的第一个&ldquo;&lt;&rdquo;。下一个正则记号是&ldquo;.&rdquo;。这次是一个懒惰的&ldquo;+&rdquo;来重复上一个字符。这告诉正则引擎，尽可能少的重复上一个字符。因此引擎匹配&ldquo;.&rdquo;和字符&ldquo;E&rdquo;，然后用&ldquo;&gt;&rdquo;匹配&ldquo;M&rdquo;，结果失败了。引擎会进行回溯，和上一个例子不同，因为是惰性重复，所以引擎是扩展惰性重复而不是减少，于是&ldquo;&lt;.+&rdquo;现在被扩展为&ldquo;&lt;EM&rdquo;。引擎继续匹配下一个记号&ldquo;&gt;&rdquo;。这次得到了一个成功匹配。引擎于是报告&ldquo;&lt;EM&gt;&rdquo;是一个成功的匹配。整个过程大致如此。</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>惰性扩展的一个替代方案</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">我们还有一个更好的替代方案。可以用一个贪婪重复与一个取反字符集：&ldquo;&lt;[^&gt;]+&gt;&rdquo;。之所以说这是一个更好的方案在于使用惰性重复时，引擎会在找到一个成功匹配前对每一个字符进行回溯。而使用取反字符集则不需要进行回溯。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">最后要记住的是，本教程仅仅谈到的是正则导向的引擎。文本导向的引擎是不回溯的。但是同时他们也不支持惰性重复操作。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>7.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>使用&ldquo;.</b><b>&rdquo;匹配几乎任意字符</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">在正则表达式中，&ldquo;.&rdquo;是最常用的符号之一。不幸的是，它也是最容易被误用的符号之一。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&ldquo;.&rdquo;匹配一个单个的字符而不用关心被匹配的字符是什么。唯一的例外是新行符。在本教程中谈到的引擎，缺省情况下都是不匹配新行符的。因此在缺省情况下，&ldquo;.&rdquo;等于是字符集[^\n\r](Window)或[^\n]( Unix)的简写。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">这个例外是因为历史的原因。因为早期使用正则表达式的工具是基于行的。它们都是一行一行的读入一个文件，将正则表达式分别应用到每一行上去。在这些工具中，字符串是不包含新行符的。因此&ldquo;.&rdquo;也就从不匹配新行符。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">现代的工具和语言能够将正则表达式应用到很大的字符串甚至整个文件上去。本教程讨论的所有正则表达式实现都提供一个选项，可以使&ldquo;.&rdquo;匹配所有的字符，包括新行符。在RegexBuddy, EditPad Pro或PowerGREP等工具中，你可以简单的选中&ldquo;点号匹配新行符&rdquo;。在Perl中，&ldquo;.&rdquo;可以匹配新行符的模式被称作&ldquo;单行模式&rdquo;。很不幸，这是一个很容易混淆的名词。因为还有所谓&ldquo;多行模式&rdquo;。多行模式只影响行首行尾的锚定(anchor)，而单行模式只影响&ldquo;.&rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">其他语言和正则表达式库也采用了Perl的术语定义。当在.NET Framework中使用正则表达式类时，你可以用类似下面的语句来激活单行模式：Regex.Match(&ldquo;string&rdquo;,&rdquo;regex&rdquo;,RegexOptions.SingleLine)</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>保守的使用点号&ldquo;.&rdquo;</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">点号可以说是最强大的元字符。它允许你偷懒：用一个点号，就能匹配几乎所有的字符。但是问题在于，它也常常会匹配不该匹配的字符。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">我会以一个简单的例子来说明。让我们看看如何匹配一个具有&ldquo;mm/dd/yy&rdquo;格式的日期，但是我们想允许用户来选择分隔符。很快能想到的一个方案是&lt;&lt;\d\d.\d\d.\d\d&gt;&gt;。看上去它能匹配日期&ldquo;02/12/03&rdquo;。问题在于02512703也会被认为是一个有效的日期。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\d\d[-/.]\d\d[-/.]\d\d&gt;&gt;看上去是一个好一点的解决方案。记住点号在一个字符集里不是元字符。这个方案远不够完善，它会匹配&ldquo;99/99/99&rdquo;。而&lt;&lt;[0-1]\d[-/.][0-3]\d[-/.]\d\d&gt;&gt;又更进一步。尽管他也会匹配&ldquo;19/39/99&rdquo;。你想要你的正则表达式达到如何完美的程度取决于你想达到什么样的目的。如果你想校验用户输入，则需要尽可能的完美。如果你只是想分析一个已知的源，并且我们知道没有错误的数据，用一个比较好的正则表达式来匹配你想要搜寻的字符就已经足够。</div>
<div style="margin: 0in 0in 0pt"><b>&nbsp;</b></div>
<div style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><b><span>8.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b><b>字符串开始和结束的锚定</b></div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">锚定和一般的正则表达式符号不同，它不匹配任何字符。相反，他们匹配的是字符之前或之后的位置。&ldquo;^&rdquo;匹配一行字符串第一个字符前的位置。&lt;&lt;^a&gt;&gt;将会匹配字符串&ldquo;abc&rdquo;中的a。&lt;&lt;^b&gt;&gt;将不会匹配&ldquo;abc&rdquo;中的任何字符。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">类似的，$匹配字符串中最后一个字符的后面的位置。所以&lt;&lt;c$&gt;&gt;匹配&ldquo;abc&rdquo;中的c。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.25in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>锚定的应用</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">在编程语言中校验用户输入时，使用锚定是非常重要的。如果你想校验用户的输入为整数，用&lt;&lt;^\d+$&gt;&gt;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">用户输入中，常常会有多余的前导空格或结束空格。你可以用&lt;&lt;^\s*&gt;&gt;和&lt;&lt;\s*$&gt;&gt;来匹配前导空格或结束空格。</div>
<div style="margin: 0in 0in 0pt">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>使用&ldquo;^&rdquo;和&ldquo;$&rdquo;作为行的开始和结束锚定</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">如果你有一个包含了多行的字符串。例如：&ldquo;first line\n\rsecond line&rdquo;(其中\n\r表示一个新行符)。常常需要对每行分别处理而不是整个字符串。因此，几乎所有的正则表达式引擎都提供一个选项，可以扩展这两种锚定的含义。&ldquo;^&rdquo;可以匹配字串的开始位置(在f之前)，以及每一个新行符的后面位置(在\n\r和s之间)。类似的，$会匹配字串的结束位置(最后一个e之后)，以及每个新行符的前面(在e与\n\r之间)。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">在.NET中，当你使用如下代码时，将会定义锚定匹配每一个新行符的前面和后面位置：Regex.Match(&quot;string&quot;, &quot;regex&quot;, RegexOptions.Multiline)</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">应用：string str = Regex.Replace(Original, &quot;^&quot;, &quot;&gt; &quot;, RegexOptions.Multiline)--将会在每行的行首插入&ldquo;&gt; &rdquo;。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&nbsp;</div>
<div style="margin: 0in 0in 0pt 0.3in; text-indent: -0.25in"><span>&middot;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>绝对锚定</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">&lt;&lt;\A&gt;&gt;只匹配整个字符串的开始位置，&lt;&lt;\Z&gt;&gt;只匹配整个字符串的结束位置。即使你使用了&ldquo;多行模式&rdquo;，&lt;&lt;\A&gt;&gt;和&lt;&lt;\Z&gt;&gt;也从不匹配新行符。</div>
<div style="margin: 0in 0in 0pt; text-indent: 0.3in">即使\Z和$只匹配字符串的结束位置，仍然有一个例外的情况。如果字符串以新行符结束，则\Z和$将会匹配新行符前面的位置，而不是整个字符串的最后面。这个&ldquo;改进&rdquo;是由Perl引进的，然后被许多的正则表达式实现所遵循，包括Java，.NET等。如果应用&lt;&lt;^[a-z]+$&gt;&gt;到&ldquo;joe\n&rdquo;，则匹配结果是&ldquo;joe&rdquo;而不是&ldquo;joe\n&rdquo;。<br />
&nbsp;</div>]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/178.htm</link>
			<title><![CDATA[公式编辑工具]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Wed,10 Jun 2009 10:46:40 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=178</guid>
		<description><![CDATA[<p><a href="http://www.numberempire.com/texequationeditor/equationeditor.php">http://www.numberempire.com/texequationeditor/equationeditor.php</a><br />
以下是一个js代码的公式编辑器</p>
<p>代码为&lt;script src=&quot;http://www.gmodules.com/ig/ifr?url=http://www.sitmo.com/gg/latex/latex.xml&amp;amp;up_eq=&amp;amp;up_z=100&amp;amp;synd=open<br />
&amp;amp;w=320&amp;amp<br />
;h=500&amp;amp;title=Equation+Editor&amp;amp;border=%23ffffff%7C3px%2C1px+solid+%23999999&amp;amp;output=js&quot;&gt;&lt;/script&gt;</p>
<script src="http://www.gmodules.com/ig/ifr?url=http://www.sitmo.com/gg/latex/latex.xml&amp;up_eq=&amp;up_z=100&amp;synd=open&amp;w=320&amp;h=500&amp;title=Equation+Editor&amp;border=%23ffffff%7C3px%2C1px+solid+%23999999&amp;output=js"></script>
<p>这是一个包含公式的页面<a href="http://www.mathfan.com/CMS/node/17">http://www.mathfan.com/CMS/node/17</a></p>
<p>&nbsp;</p>]]></description>
		</item>
		
			<item>
			<link>http://www.tomliao.cn/article/computer/164.htm</link>
			<title><![CDATA[微软10月中旬发布正式版Win7]]></title>
			<author>gang2005188[at]sina.com(小刚)</author>
			<category><![CDATA[计算机]]></category>
			<pubDate>Wed,03 Jun 2009 15:00:18 +0800</pubDate>
			<guid>http://www.tomliao.cn/default.asp?id=164</guid>
		<description><![CDATA[令人期待的Windows 7将要出来了。<br/><br/>北京时间今天凌晨消息，据国外媒体报道，微软周二确认称，该公司计划于10月22日在零售店铺中出售Windows 7，同时开始在新PC上预装这一操作系统。　　<br/>微软高级副总裁比尔·维迪(Bill Veghte)在今天接受采访时称，微软计划在下个月中旬或月底以前完成Windows 7的开发进程。他表示：“市场对RC(发布候选)版Windows 7的回馈信息一直十分良好。”　　微软上个月发布了RC版Windows 7，此后不久就最终确认称，该公司计划在2009年假期季节发布正式版。　　<br/><br/>由于人呢对于前一个版本vista 失望，这一次的新版本Windows 7希望能令人满意。<br/><br/><br/>惠普个人系统集团首席技术官菲尔·麦肯尼(Phil McKinney)在接受采访时称，他对微软发布正式版Windows 7的日期感觉良好，“我们正在等待Windows 7的发布，这一操作系统的编码质量相当的好。”　<br/>]]></description>
		</item>
		
</channel>
</rss>
