<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>李卫公的长安城</title>
	<atom:link href="http://blog.donews.com/maverick/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.donews.com/maverick</link>
	<description>过上一万年，那城就会变成黑色，永远不倒……</description>
	<lastBuildDate>Mon, 27 Oct 2008 13:11:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>正则表达式不是万能的</title>
		<link>http://blog.donews.com/maverick/archive/2008/09/05/1342873.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2008/09/05/1342873.aspx#comments</comments>
		<pubDate>Fri, 05 Sep 2008 06:34:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[开发]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2008/09/05/1342873.aspx</guid>
		<description><![CDATA[经常会有人问起正则表达式的问题，常见的形式是：要解决这个问题，该怎么写正则表达式？

OK，常见的某些问题，正则表达式应用起来的确得心应手。譬如，验证一个字符串是否数字字符串，\d+\，确实比逐个检查字符，用“或”连接10个判断（是否0－9之间的字符）要方便。

然而，正则表达式终究是一种工具，功能再强大，也不是万能的。许多时候，仅仅希望依靠正则表达式，更准确地说，是“一条”正则表达式来完成任务，反而会走远路。]]></description>
			<content:encoded><![CDATA[<p>经常会有人问起正则表达式的问题，常见的形式是：要解决这个问题，该怎么写正则表达式？</p>
<p>OK，常见的某些问题，正则表达式应用起来的确得心应手。譬如，验证一个字符串是否数字字符串，\d+\，确实比逐个检查字符，用&ldquo;或&rdquo;连接10个判断（是否0－9之间的字符）要方便。</p>
<p>然而，正则表达式终究是一种工具，功能再强大，也不是万能的。许多时候，仅仅希望依靠正则表达式，更准确地说，是&ldquo;一条&rdquo;正则表达式来完成任务，反而会走远路。</p>
<p>譬如要找出这样的字符串：<span style="color: rgb(0, 0, 255); font-weight: bold;">aba, aabaa, aaabaaa&hellip;&hellip;</span><br />也就是这样的字符串：在字母b的前后，字母a连续出现的次数一样多<br />这种问题，正则表达式确实能解决。但如果要仅仅用&ldquo;一条正则表达式&rdquo;来解决，目前只有Perl的正则表达式强大到这种程度，其它语言中的正则表达式，恐怕做不到这一点。<br />怎么办呢？其实，我们只需要另外加上一个判断作为辅助，就好了：<br />正则表达式写作 <br /><span style="color: rgb(255, 0, 0); font-weight: bold;">(?&lt;!a)(a+)b(a+)(?!a)</span><br />然后比较group 1和group 2的长度，就可以满足要求了。<br />这里解释一下开头和结尾的两个结构：</p>
<ul>
<li><span style="color: rgb(255, 0, 0); font-weight: bold;">(?&lt;!a)</span>表示这个正则表达式匹配文本的左端（而不是在匹配文本之内）不能是字符a，可以是其它任何字符（甚至没有字符）。</li>
<li><span style="font-weight: bold; color: rgb(255, 0, 0);">(?=!a)</span>表示这个正则表达式匹配文本的右端（而不是在匹配文本之内）不能是字符a，可以是其它任何字符（甚至没有字符）。</li>
</ul>
<p>在应用正则表达式时，记住添加一些用于判断的&ldquo;锚点&rdquo;(anchor)，准确地表达我们的意图，是一个好习惯。</p>
<p>另一类常见的问题是，没有找到合适的思路，于是写不出正确的表达式。</p>
<p>譬如要处理类似这样的字符串（这个字符串太神奇，但确实有人问起）：<br /><span style="color: rgb(0, 0, 255);">printf(&quot;%d; %d; %d;&quot;, ％a, %b, %c);</span><br />去掉引号外的％。<br />&ldquo;我要怎么用正则表达式来表示&ldquo;引号外部&rdquo;的概念呢？&rdquo;，这个朋友被困住了。<br />但是，我们仔细观察就会发现，其实我们真正关注的不是&ldquo;引号外部&rdquo;，而是引号字符串（也就是表示格式的字符串）之后的内容，也就是说，最后一个引号右边的内容，仔细观察就会发现，其中文字的特点是，它们的右边都没有引号，于是问题就变成了，&ldquo;去掉这样的百分号，它右边的字符串中不包含引号&rdquo;。<br />于是我们很顺利地写出正则表达式<br /><span style="color: rgb(255, 0, 0); font-weight: bold;">%(?=[^&quot;]*$)</span><br />这里，一定不要忘记添加$，这样，括号内的结构才能匹配右边的所有字符，而不是其中的一串字符。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2008/09/05/1342873.aspx/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>五一节掠影</title>
		<link>http://blog.donews.com/maverick/archive/2008/05/02/1285450.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2008/05/02/1285450.aspx#comments</comments>
		<pubDate>Fri, 02 May 2008 03:06:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[点点滴滴]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2008/05/02/1285450.aspx</guid>
		<description><![CDATA[<img src="http://www.luanxiang.org/blog/wp-content/uploads/2008/05/amazon.jpg" alt="" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.luanxiang.org/blog/wp-content/uploads/2008/05/amazon.jpg" alt="" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2008/05/02/1285450.aspx/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>技之所在，艺之所倚</title>
		<link>http://blog.donews.com/maverick/archive/2008/04/07/1274255.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2008/04/07/1274255.aspx#comments</comments>
		<pubDate>Mon, 07 Apr 2008 06:44:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[点点滴滴]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2008/04/07/1274255.aspx</guid>
		<description><![CDATA[数据库？不就是MySQL之类嘛！
关系？不就是表嘛！
数据库设计？对着界面就能想出来嘛！
考虑不周全？改表嘛！
速度不够快？你建索引了吗？加索引嘛！
……
在我的开发经验中，类似的问答并不罕见。可是，这正常吗？]]></description>
			<content:encoded><![CDATA[<p>数据库？不就是MySQL之类嘛！<br />关系？不就是表嘛！<br />数据库设计？对着界面就能想出来嘛！<br />考虑不周全？改表嘛！<br />速度不够快？你建索引了吗？加索引嘛！<br />&hellip;&hellip;<br />在我的开发经验中，类似的问答并不罕见。可是，这正常吗？<br />如今，DBMS似乎已经成了大多数应用中数据持久化当仁不让的选择；而大量的开发场合里，并没有专职的DBA存在，于是，数据库的安装、设计、维护、操作，往往由程序员兼任。不幸的是，在不少程序员那里，数据库的知识却是非常匮乏的&mdash;&mdash;否则，就不会有上面这些问答了。<br />这也难怪，学校开设的数据库课程，往往太过古老&mdash;&mdash;不少课本还在讲Foxbase（把课程当考古呢）；太过枯燥&mdash;&mdash;1NF、2NF、3NF、BCNF，想想就头疼（况且有过开发经验的人都知道，很多时侯不能完全规范化呢）；太过理论化&mdash;&mdash;索引的检索比率（retrieve ratio）在10%左右是正常的（拜托，说那话的时候500,000行数据就算大表了，如今，这样的表司空见惯吧）&hellip;&hellip;况且，如今的DBMS又这么智能，这么易用，索性彻底打破那些条条框框，按照直觉，怎样趁手就怎样来，似乎也是个不错的选择。<br />然而，问题似乎并不是这么简单，尤其是在应用日益复杂，对速度的要求又愈来愈严格的今天&mdash;&mdash;数据库没设计好，复杂应用或是无法实现，或是效率极低；SQL语句写的不够简洁高效，速度就会大打折扣。日常开发中，这样的例子屡见不鲜：两条结果相同的SQL语句，一条需要0.05秒，一条需要0.2秒，如果一天执行50,000次，时间差别就是将近2小时！我见过某个普遍使用的论坛程序中，会把整个数据库锁死172秒的SQL语句；也遇见过设计不当的数据库，在里面60秒钟才能完成本来只需要5秒的查询。<br />每次遇到这种情况，我都在想，如果有一本书，从实际出发，教给我们&ldquo;真正实用&rdquo;的数据库的知识，该多好？</p>
<p>O&rsquo;Reilly的<a href="http://www.china-pub.com/38677">the Art of SQL</a>，就是这样一本书！<br />光看名字，这本书讲的是SQL语言的&ldquo;技艺&rdquo;，然而随便翻阅两页，你就会发现，这其实是一本数据库实战全书。它的内容巨细靡遗，上至数据库设计的整体思想，下至SQL语句的调优细节；而且针对各种实际开发中遇到的各类典型问题，不但给出了解决方案，更给出了理由：<br />一家公司，会计部门、办公部门和生产部门的地址可能各不相同，我们该怎么办？留出三个字段吗？可是许多大多数时候，一个地址就够了，那么，另两个地址设为NULL，还是直接复制数据？如果设为NULL，判断并读取地址的操作，是应该放在数据库中呢，还是程序语言中呢？如果复制数据，如何保持更新的一致性呢？ <br />如果要判断是否存在合适的数据，再做修改，应该先用count(*)吗？可是，有经验的程序员似乎有另外的办法，他们是怎么做的呢？<br />教科书上说，规范化是必须的，但是，有时候去规范化也是必须的，什么情况下应该去规范化，我们如何判断呢？<br />更多的索引能够带来更高的效率吗？系统地为外键建立索引，真的是良好的习惯吗？如果已经建立了多字段索引，是否还有必要为其中某个字段单独建索引？<br />数据量大了，表分区（或者&ldquo;表空间&rdquo;）是个不错的解决办法。然而，该如何分区呢？什么情况下选择循环分区？什么情况下选择数据驱动分区？<br />复杂的数据处理逻辑，是应该放到数据库内部（PL/SQL），还是交给外边的程序语言（C语言）？<br />类似的问题还有很多。可以说，这样的问题，许多时候并没有固定的、现成的答案，我们必须依据具体情况，进行考量，作出抉择。此时，书中介绍的经验，给出的抉择指导、判断依据，就显得尤其珍贵了。<br />除此之外，这本书还有两个地方深得我喜爱：一点是介绍了好的开发习惯，譬如在每条SQL语句开头加上注释，以便调试（相信我，在复杂系统中，这个习惯非常、非常有用）；另一点是，作者写书借用了《孙子兵法》的智慧，所举的例子也多与军事有关&mdash;&mdash;譬如介绍索引时，所用的数据就是拿破仑麾下战将的名字&mdash;&mdash;我相信，&ldquo;好程序员大都不专注&rdquo;，所以对军事有兴趣的程序员，应该能体会到更多的妙趣。</p>
<p>关系数据库与软件开发中的其它许多领域不同，它有完备的理论基础，又必须融入纷繁复杂的现实。the Art of SQL，或许更适合翻译为《SQL的技艺》，因为它是理论与现实之间，一座经验的桥梁。</p>
<p><a href="http://www.china-pub.com/38677"><img src="http://images.china-pub.com/ebook35001-40000/38677/zcover.jpg" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2008/04/07/1274255.aspx/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>解决Gmail连接被阻断的问题</title>
		<link>http://blog.donews.com/maverick/archive/2007/12/14/1236608.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2007/12/14/1236608.aspx#comments</comments>
		<pubDate>Fri, 14 Dec 2007 01:32:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[点点滴滴]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2007/12/14/1236608.aspx</guid>
		<description><![CDATA[在用浏览器访问Gmail时，经常会遇到这样的情况，登录成功，但马上便提示无法连接服务器，这其实是因为Gmail的Web页面默认启用的聊天功能被GFW所致，解决的办法就是关掉Web中的聊天功能，具体设置如。]]></description>
			<content:encoded><![CDATA[<p>在用浏览器访问Gmail时，经常会遇到这样的情况，登录成功，但马上便提示无法连接服务器，这其实是因为Gmail的Web页面默认启用的聊天功能被GFW所致，解决的办法就是关掉Web中的聊天功能，具体设置如。</p>
<p>下面的截图是登录Gmail之后，在浏览器最下边显示的信息。在默认情况下，用户的选项是最左边的&ldquo;standard with chat&rdquo;，我们登录Gmail之后，抢在连接被阻断之前，选择&ldquo;standard without chat&rdquo;，就可以了。</p>
<p><img src="http://www.luanxiang.org/blog/wp-content/uploads/2007/12/gmail_firefox.JPG" alt="" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2007/12/14/1236608.aspx/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>开发经验谈：正则表达式与字符串</title>
		<link>http://blog.donews.com/maverick/archive/2007/10/18/1220416.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2007/10/18/1220416.aspx#comments</comments>
		<pubDate>Thu, 18 Oct 2007 04:33:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[开发]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2007/10/18/1220416.aspx</guid>
		<description><![CDATA[在日常应用正则表达式时，经常遇到的一类问题是，弄不清楚到底该如何转义——最明显的表现就是，搞不懂究竟要使用多少个反斜线，大部分时候，只好盲目尝试，直到测试成功为止。但是，许多时候，这样的方法并不能完整解决问题。
为了彻底解决这类问题，我们需要弄清楚正则表达式与字符串的关系：它其实很简单，根据我的经验，我们只需要牢记下面两条原则：]]></description>
			<content:encoded><![CDATA[<p>(欢迎转载，转载请注明出处)</p>
<p>在日常应用正则表达式时，经常遇到的一类问题是，弄不清楚到底该如何转义&mdash;&mdash;最明显的表现就是，搞不懂究竟要使用多少个反斜线，大部分时候，只好盲目尝试，直到测试成功为止。但是，许多时候，这样的方法并不能完整解决问题。<br />为了彻底解决这类问题，我们需要弄清楚正则表达式与字符串的关系：它其实很简单，根据我的经验，我们只需要牢记下面两条原则：</p>
<p>1.正则表达式不等于字符串，但必须以字符串的形式给出</p>
<p>大多数语言中都存在正则表达式（regex）对象，譬如Java语言中的Pattern对象，即使没有提供专门的对象，也需要用某些特殊的字符来标注正则表达式，譬如PHP中常用的反斜线&lsquo;/&rsquo;。另一方面，正则表达式对某些字符或字符序列有自己的规定，不同于字符串的规定，譬如&lsquo;\b&rsquo;在正则表达式中表示单词分界符，而在普通字符串中表示退格字符。因此我们可以说，正则表达式并不等于普通的字符串。<br />但是，正则表达式又终究是一种处理文本的语言，因此，我们写出的所有正则表达式，都是以字符串形式提供的。<br />所以，在应用正则表达式的过程中，需要进行从字符串到正则表达式本身的转换。<br />也就是<br />&ldquo;源代码中的字符序列&rdquo;-&gt;&ldquo;字符串&rdquo;-&gt;&ldquo;正则表达式&rdquo;</p>
<p>譬如，在Java语言中，正则表达式中的&lsquo;\b&rsquo;，在以字符串表示时，必须写做<br />String regex = &quot;\\b&quot;;<br />其中第1个反斜线用来转义第2个反斜线，这样，正则表达式接受到的才是真正的&lsquo;\b&rsquo;，对应正则表达式中的单词分界符，如果我们写<br />String regex = &quot;\b&quot;;<br />编译也没有问题，但此时正则表达式接受的是一个字符，即退格符。</p>
<p>需要注意的是，在Java和C#之类的语言中，如果字符串中出现的字符序列无法识别，编译会出错，譬如这样：<br />String regex = &quot;\w&quot;;<br />编译无法通过，因为根据字符串的规定，&lsquo;\w&rsquo;不是一个合法的转义序列，在字符串这一关就卡住了。</p>
<p>但是在PHP和Python之类的语言中，这样写却没有问题。原因在于，如果PHP和Python发现字符串中有无法识别的转义序列，会原封不动地保存下来，这样，正则表达式接受到的，仍然是&lsquo;\w&rsquo;。<br />当然，我们也可以在这些语言中使用&lsquo;\\w&rsquo;，结果是一样的，因为此时，在进行字符串处理时，第1个反斜线转义了第2个反斜线，正则表达式接受到的，仍然是&lsquo;\w&rsquo;。</p>
<p>这是在实际开发中非常迷惑人的一点，只要我们弄清了正则表达式和字符串的关系，就不会再感到迷惑。</p>
<p>2.正则表达式中单独出现的反斜线也需要转义</p>
<p>在正则表达式中，反斜线通常与其它字符一起构成特殊的结构，譬如&lsquo;\d&rsquo;用来匹配数字字符，&lsquo;\s&rsquo;用来匹配空白字符，&lsquo;\1&rsquo;用来反向引用第一个分组捕获的文本。<br />可是，如果我们在正则表达式中，仅仅需要表示&ldquo;反斜线&rdquo;字符本身，该如何做呢？<br />其实，正则表达式对这个问题的处理，与字符串的处理是一样的，也就是说，在正则表达式中，必须用转义序列&lsquo;\\&rsquo;来表示单个反斜线。<br />这个规定会带来一个有趣的问题：正则表达式中单独出现的反斜线字符，在正则表达式的层面，必须以转义序列&lsquo;\\&rsquo;来表示，然而，每个反斜线，在表示正则表达式的字符串中，又必须以转义序列&lsquo;\\&rsquo;来表示。所以，在字符串中，必须写出四个反斜线&lsquo;\\\\&rsquo;，才能对应到正则表达式中单独出现的一个反斜线字符：在字符串处理层面，它们会被识别为两个反斜线&lsquo;\\&rsquo;，在正则表达式的层面，它们会被识别为单个反斜线字符&lsquo;\&rsquo;。</p>
<p>很麻烦，很困惑，但是，其实也不难明白，对吗？</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2007/10/18/1220416.aspx/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>开发笔记：MySQL的维护语句</title>
		<link>http://blog.donews.com/maverick/archive/2007/09/28/1214300.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2007/09/28/1214300.aspx#comments</comments>
		<pubDate>Fri, 28 Sep 2007 05:51:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[开发]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2007/09/28/1214300.aspx</guid>
		<description><![CDATA[Analyze Table

MySQL的Optimizer（优化元件）在优化SQL语句时，首先需要收集一些相关信息，其中就包括表的cardinality（可以翻译为“散列程度”），它表示某个索引对应的列包含多少个不同的值——如果cardinality大大少于数据的实际散列程度，那么索引就基本失效了。
我们可以使用SHOW INDEX语句来查看索引的散列程度：]]></description>
			<content:encoded><![CDATA[<p><span style="color: rgb(255, 0, 0); font-weight: bold;">Analyze Table</span></p>
<p>MySQL的Optimizer（优化元件）在优化SQL语句时，首先需要收集一些相关信息，其中就包括表的cardinality（可以翻译为&ldquo;散列程度&rdquo;），它表示某个索引对应的列包含多少个不同的值&mdash;&mdash;如果cardinality大大少于数据的实际散列程度，那么索引就基本失效了。<br />我们可以使用SHOW INDEX语句来查看索引的散列程度：</p>
<p><span style="color: rgb(0, 0, 255);">SHOW INDEX FROM PLAYERS;</span></p>
<p>TABLE&nbsp;&nbsp; KEY_NAME COLUMN_NAME CARDINALITY<br />&#8212;&#8212;- &#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211;<br />PLAYERS PRIMARY&nbsp; PLAYERNO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14</p>
<p>因为此时PLAYER表中不同的PLAYERNO数量远远多于14，索引基本失效。<br />下面我们通过Analyze Table语句来修复索引：</p>
<p><span style="color: rgb(0, 0, 255);">ANALYZE TABLE PLAYERS;</span><br style="color: rgb(0, 0, 255);" /><span style="color: rgb(0, 0, 255);">SHOW INDEX FROM PLAYERS;</span><br />结果是：<br />TABLE&nbsp;&nbsp; KEY_NAME COLUMN_NAME CARDINALITY<br />&#8212;&#8212;- &#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211;<br />PLAYERS PRIMARY&nbsp; PLAYERNO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1000</p>
<p>此时索引已经修复，查询效率大大提高。</p>
<p>需要注意的是，如果开启了binlog，那么Analyze Table的结果也会写入binlog，我们可以在analyze和table之间添加关键字local取消写入。</p>
<p><span style="font-weight: bold; color: rgb(255, 0, 0);">Checksum Table</span></p>
<p>数据在传输时，可能会发生变化，也有可能因为其它原因损坏，为了保证数据的一致，我们可以计算checksum（校验值）。<br />使用MyISAM引擎的表会把checksum存储起来，称为live checksum，当数据发生变化时，checksum会相应变化。<br />在执行Checksum Table时，可以在最后指定选项qiuck或是extended；qiuck表示返回存储的checksum值，而extended会重新计算checksum，如果没有指定选项，则默认使用extended。</p>
<p><span style="font-weight: bold; color: rgb(255, 0, 0);">Optimize Table</span></p>
<p>经常更新数据的磁盘需要整理碎片，数据库也是这样，Optimize Table语句对MyISAM和InnoDB类型的表都有效。<br />如果表经常更新，就应当定期运行Optimize Table语句，保证效率。<br />与Analyze Table一样，Optimize Table也可以使用local来取消写入binlog。</p>
<p><span style="font-weight: bold; color: rgb(255, 0, 0);">Check Table</span></p>
<p>数据库经常可能遇到错误，譬如数据写入磁盘时发生错误，或是索引没有同步更新，或是数据库未关闭MySQL就停止了。<br />遇到这些情况，数据就可能发生错误：<br />Incorrect key file for table: &#8216; &#8216;. Try to repair it.<br />此时，我们可以使用Check Table语句来检查表及其对应的索引。<br />譬如我们运行<br /><span style="color: rgb(0, 0, 255);">CHECK TABLE PLAYERS;</span></p>
<p>结果是<br />TABLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OP&nbsp;&nbsp;&nbsp; MSG_TYPE MSG_TEXT<br />&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8211; &#8212;&#8212;&#8211; &#8212;&#8212;&#8211;<br />TENNIS.PLAYERS check status&nbsp;&nbsp; OK</p>
<p>MySQL会保存表最近一次检查的时间，每次运行check table都会存储这些信息：</p>
<p>执行<br /><span style="color: rgb(0, 0, 255);">SELECT&nbsp;&nbsp;&nbsp; TABLE_NAME, CHECK_TIME</span><br style="color: rgb(0, 0, 255);" /><span style="color: rgb(0, 0, 255);">FROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INFORMATION_SCHEMA.TABLES</span><br style="color: rgb(0, 0, 255);" /><span style="color: rgb(0, 0, 255);">WHERE&nbsp;&nbsp;&nbsp;&nbsp; TABLE_NAME = &#8216;PLAYERS&#8217;</span><br style="color: rgb(0, 0, 255);" /><span style="color: rgb(0, 0, 255);">AND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TABLE_SCHEMA = &#8216;TENNIS&#8217;;</span></p>
<p>结果是</p>
<p>TABLE_NAME&nbsp;&nbsp; CHECK_TIME<br />&#8212;&#8212;&#8212;-&nbsp;&nbsp; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />PLAYERS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2006-08-21 16:44:25</p>
<p>Check Table还可以指定其它选项：<br />UPGRADE：用来测试在更早版本的MySQL中建立的表是否与当前版本兼容。<br />QUICK：速度最快的选项，在检查各列的数据时，不会检查链接（link）的正确与否，如果没有遇到什么问题，可以使用这个选项。<br />FAST：只检查表是否正常关闭，如果在系统掉电之后没有遇到严重问题，可以使用这个选项。<br />CHANGED：只检查上次检查时间之后更新的数据。<br />MEDIUM：默认的选项，会检查索引文件和数据文件之间的链接正确性。<br />EXTENDED：最慢的选项，会进行全面的检查。</p>
<p><span style="font-weight: bold; color: rgb(255, 0, 0);">Repair Table</span></p>
<p>用于修复表，只对MyISAM和ARCHIVE类型的表有效。<br />这条语句同样可以指定选项：<br />QUICK：最快的选项，只修复索引树。<br />EXTENDED：最慢的选项，需要逐行重建索引。<br />USE_FRM：只有当MYI文件丢失时才使用这个选项，全面重建整个索引。</p>
<p>与Analyze Table一样，Repair Table也可以使用local来取消写入binlog。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2007/09/28/1214300.aspx/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>老大哥啊老大哥</title>
		<link>http://blog.donews.com/maverick/archive/2007/09/26/1213592.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2007/09/26/1213592.aspx#comments</comments>
		<pubDate>Wed, 26 Sep 2007 03:49:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[快意恩仇]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2007/09/26/1213592.aspx</guid>
		<description><![CDATA[当年，斯大林同志对高尔基同志的《姑娘与死神》的批示，曾引起两名教授在《真理报》上撰文论证：斯大林同志之所以少写一个字母，是因为新生阶级的爱情截然不同于腐朽没落的资产阶级爱情。最后领袖再次批示：笨蛋，此系笔误。

最近，贾平凹老师又为铁凝老师的题词张罗了一次诠释。我们的表现，确实还远远比不上当年的老大哥。

奥威尔的《1984》，最后一句话是：他战胜了他自己，他热爱老大哥！看来，我们的某些同志，确实还无法战胜自己，离老大哥还差的远呢。]]></description>
			<content:encoded><![CDATA[<p>当年，斯大林同志对高尔基同志的《姑娘与死神》的批示，曾引起两名教授在《真理报》上撰文论证：斯大林同志之所以少写一个字母，是因为新生阶级的爱情截然不同于腐朽没落的资产阶级爱情。最后领袖再次批示：笨蛋，此系笔误。</p>
<p>最近，贾平凹老师又为铁凝老师的题词张罗了一次诠释。我们的表现，确实还远远比不上当年的老大哥。</p>
<p>奥威尔的《1984》，最后一句话是：他战胜了他自己，他热爱老大哥！看来，我们的某些同志，确实还无法战胜自己，离老大哥还差的远呢。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2007/09/26/1213592.aspx/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>《精通正则表达式》勘误</title>
		<link>http://blog.donews.com/maverick/archive/2007/09/14/1209937.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2007/09/14/1209937.aspx#comments</comments>
		<pubDate>Fri, 14 Sep 2007 03:01:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[点点滴滴]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2007/09/14/1209937.aspx</guid>
		<description><![CDATA[因为工作不够细致，最终版本的《精通正则表达式》还存在如下问题，只能以勘误形式发布作为补救了，请各位读者见谅。
如果大家在阅读中发现其他问题，欢迎来信指出。
yusheng.regex@gmail.com]]></description>
			<content:encoded><![CDATA[<p>因为工作不够细致，最终版本的《精通正则表达式》还存在如下问题，只能以勘误形式发布作为补救了，请各位读者见谅。<br /> 如果大家在阅读中发现其他问题，欢迎来信指出。<br /> yusheng.regex@gmail.com</p>
<hr style="width: 100%; height: 2px;" /><a href="http://www.china-pub.com/computers/common/info.asp?id=35269"><img alt="" src="http://images.china-pub.com/ebook35001-40000/35269/zcover.jpg" /></a></p>
<p>推荐序</p>
<p>vi页， 第1行， &ldquo;那它就被成为阳春应用&rdquo;，应该修改为&ldquo;那它就被称为阳春应用&rdquo;；</p>
<p>前言</p>
<p>Ⅱ页，倒数第3段，&ldquo;读这本书以前，我以为自己了解正则表达式，但现在我才真正了解&rdquo;应修改为&ldquo;读这本书以前，我以为自己了解正则表达式，但现在我才真正弄明白&rdquo;</p>
<p>Ⅱ页，倒数第2段，&ldquo;在其它任何地方都难以找到这样丰富的细节&rdquo;应修改为&ldquo;在其它任何地方都难以找到这样完整而详尽的资料&rdquo;</p>
<p>Ⅴ页，第1段，&ldquo;来开发引擎的能力，并避免其中的缺陷&rdquo;应修改为&ldquo;来发掘引擎的能力，绕开引擎的缺陷&rdquo;</p>
<p>Ⅵ页，第1段，&ldquo;[&hellip;]表示一对方括号，之间的内容无关紧要；而[&hellip;]表示一对方括号，其中包含三个句点&rdquo;应修改为&ldquo;[&hellip;]表示其间内容无关紧要的一对方括号，而[&hellip;]表示包含三个句点的方括号&rdquo;</p>
<p>第1章</p>
<p>2页，倒数第2段，&ldquo;但是它不一定能代表正则表达式在平时解决的那些&ldquo;不值一提&rdquo;（uninteresting）的问题。这里的&ldquo;不值一提&rdquo;是指这类问题并不能成为谈 资，可是不解决它们，你就没法继续干活&rdquo;应修改为&ldquo;但是正则表达式在平时还用来解决那些&ldquo;讨人厌（uninteresting）&rdquo;的问题。说&ldquo;讨人厌&rdquo;， 是因为它们不适合跟外人吹嘘，可是不解决它们，你就没法继续干活&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">3页，第12行，&ldquo;^(From|Sbuject):&rdquo;应修改为&ldquo;^(From|Subject):&rdquo;</span><br /> <br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">6页，标题&ldquo;正则表达式的思维框架&rdquo;应修改为&ldquo;理解正则表达式的结构&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">9页，倒数第3段，&ldquo;在搜索HTML代码的头文件时这非常有用&rdquo;应修改为&ldquo;在搜索HTML Header时这非常有用&rdquo;</span></p>
<p>12页，注4中&ldquo;作为一个小孩子，那时候我感觉非常受伤&rdquo;应修改为&ldquo;当时我还是个孩子，很伤心&rdquo;<span style="color: rgb(255, 0, 0);"></span><br style="color: rgb(255, 0, 0);" /><br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">14页，第4段，&ldquo;匹配一行的起始位置，然后匹配「^From」、「Subject」或「Date」中的任意一个&rdquo;应修改为&ldquo;匹配一行的起始位置，然后匹配「From」、「Subject」或「Date」中的任意一个&rdquo;</span></p>
<p>15页，第3段，&ldquo;我使用-i参数的频率很高&rdquo;应修改为&ldquo;我经常使用-i参数&rdquo;</p>
<p>15页，倒数第4段，&ldquo;&gt;&rdquo;字符不应该是黑体</p>
<p>17页，倒数第3段，&ldquo;无论u是否出现，匹配都是成功的&rdquo;应修改为&ldquo;无论u是否出现，匹配都会成功&rdquo;</p>
<p>18页，倒数第3段，&ldquo;因为它们限定了所作用元素的匹配次数&rdquo;应修改为&ldquo;因为它们限定了所作用元素的重现次数&rdquo;</p>
<p>19页，第2段，&ldquo;一个字符组是一个&ldquo;元素&rdquo;（unit），所以它可以直接加加号、星号等，而不需要用括号&rdquo;应修改为&ldquo;一个字符组就是一个&ldquo;元素&rdquo;（unit），可以对它直接使用加号、星号等，而不需要括号&rdquo;</p>
<p>19页，倒数第1段，&ldquo;每个量词都规定了匹配成功至少需要的次数下限，以及尝试匹配的次数上限&rdquo;应修改为&ldquo;每个量词都规定了匹配成功至少需要的重现次数下限，以及尝试匹配的重现次数上限&rdquo;<br /> <br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">20页，表1-2中：&ldquo;可以不出现，也可以只出现一次&rdquo;修改为&ldquo;可以出现，也可以只重现一次&rdquo;；&ldquo;可以出现无数次，也可以不出现&rdquo;修改为&ldquo;可以重现无穷多次，也可以不出现&rdquo;； &ldquo;可以出现无数次，但至少要出现一次&rdquo;修改为&ldquo;可以重现无穷多次，但至少要出现一次&rdquo;</span></p>
<p>21页，倒数第2段，&ldquo;这并不是正则表达式的错误&rdquo;应修改为&ldquo;正则表达式对此无能为力&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">27 页，第1段，&ldquo;而且说&ldquo;如果你写一个正则&rdquo;，&ldquo;巧妙的正则&rdquo;（budding regexers），甚至是&ldquo;正则化&rdquo;（regexification）&rdquo;修改为&ldquo;而且说&ldquo;如果你写一个正则&rdquo;，&ldquo;巧妙的正则&rdquo;（budding regexers），甚至是&ldquo;正则化&rdquo;（regexification）听起来更顺一些。我说的&ldquo;正则引擎（regex engine）&rdquo;指的是程序中实际执行匹配尝试的那个部分&rdquo;</span></p>
<p>第2章</p>
<p>37页，第1段，&ldquo;它们都非常不同于&ldquo;传统&rdquo;的语言，例如C和Pascal&rdquo;应修改为&ldquo;它们截然不同于C和Pascal之类&ldquo;传统&rdquo;的语言&rdquo;</p>
<p>37页，第13行，&ldquo;print &ldquo;celsuius C is &hellip; #返回摄氏和华氏温度&rdquo; 应修改为 &ldquo;print &ldquo;celsuius C is &hellip; #输出摄氏和华氏温度&rdquo;</p>
<p>38页，倒数第1段，&ldquo;运算符==用来测试两个数字是否相等&rdquo;修改为&ldquo;运算符==用来测试两个数值是否相等&rdquo;</p>
<p>40 页，第1段，&ldquo;我不想在本章中讨论Perl的细节，但是我告诉你用printf（&ldquo;格式化输出（print formatted）&rdquo;）可以解决这个问题&rdquo;修改为&ldquo;我不想在本章中讨论Perl的细节，不过我还是想说，printf（&ldquo;格式化输出（print formatted）&rdquo;）可以解决这个问题&rdquo;</p>
<p>40页，第3段，&ldquo;Perl通常情况下不区分整数和浮点数&rdquo;修改为&ldquo;Perl一般不区分整数和浮点数&rdquo;</p>
<p>41页，倒数第1段，&ldquo;我们发现，这个图让我们很容易地决定匹配之后应该干什么&rdquo;修改为&ldquo;看了这张图，我们很容易就能决定匹配之后应该干什么&rdquo;</p>
<p>46页，补充内容的最后1段，&ldquo;尽管因为第4章将会解释其原因，字符组的效率通常还是会高一点&rdquo;修改为&ldquo;不过根据第4章解释的原因，字符组的效率通常要高一些&rdquo;</p>
<p style="color: rgb(255, 0, 0);">56页，倒数第2行，&ldquo;^From: (\s+) \&rdquo;修改为&ldquo;^From: (\S+) \&rdquo;（S的大小写不同）</p>
<p style="color: rgb(255, 0, 0);">57页，第3行，&ldquo;^From: (\s+) \&rdquo;修改为&ldquo;^From: (\S+) \&rdquo;（S的大小写不同）</p>
<p><span style="color: rgb(255, 0, 0);">67页，第3段下面，正则表达式&ldquo;$text =~ s/(\d)(?=(\d\d\d)+(?!\d)/$1,/g&rdquo;应修改为&ldquo;$text =~ s/(\d)(?=(\d\d\d)+(?!\d)</span><font color="#ff0000" style="color: rgb(255, 0, 0);">)</font><span style="color: rgb(255, 0, 0);">/$1,/g&rdquo;，少了一个括号</span><br style="color: rgb(255, 0, 0);" /> <br style="color: rgb(255, 0, 0);" /> <span style="color: rgb(255, 0, 0);">70页，第2段，所以整个正则表达式的意义就不再是&ldquo;寻找空行及只包含空白字符的行&rdquo;，而是&ldquo;寻找连续、空行和只包括空白字符的行的结合&rdquo;</span><br style="color: rgb(255, 0, 0);" /> <span style="color: rgb(255, 0, 0);">应修改为</span><br style="color: rgb(255, 0, 0);" /> <span style="color: rgb(255, 0, 0);">所以整个正则表达式的意义就不再是&ldquo;寻找空行或只包含空白字符的行&rdquo;，而是&ldquo;寻找空行和只包含空白字符的行的结合&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">76页，倒数第2段，&ldquo;此外，我们的匹配主机名的正则表达式只存在一个&ldquo;主源（main source）&rdquo;&rdquo;应修改为&ldquo;此外，我们的匹配主机名的正则表达式只存在一个&ldquo;源头（main source）&rdquo;，&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">第78页<br />示例2-3中第4标注<br />{\e[7m$1\e[m$2\e[7m$3\e[m ] igx;<br />应修改为<br />{\e[7m$1\e[m$2\e[7m$3\e[m } igx;<br /></span></p>
<p>第3章</p>
<p><span style="color: rgb(255, 0, 0);">89页，第1段，&ldquo;不支持字符组中的\w（完全不支持\d和\s）&rdquo;应修改为&ldquo;在字符组中无法使用\w（\d和\s在任何地方都无法使用）&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">92页，倒数第2段，&ldquo;在极端的情况下，反向引用的&ldquo;行为&rdquo;有意义吗？&rdquo;应修改为&ldquo;在极端的情况下，反向引用还能正常工作吗？&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">93页，第12行，&rdquo;┌(July|Jul)┘和┌\(July\|Jul\)┘能够取得同样的匹配结果&hellip;&ldquo;应修改为&rdquo;┌(Jul|July)┘和┌\(July\|Jul\)┘能够取得同样的匹配结果&hellip;&ldquo;</span><br /> <br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">95页，标题&ldquo;函数式处理的例子&rdquo;应修改为&ldquo;程序式处理的例子&rdquo;</span><br style="color: rgb(255, 0, 0);" /><br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">95页，倒数第1段，&ldquo;不过，Java也提供了一些函数式处理的&hellip;&hellip;&rdquo;应修改为&ldquo;不过，Java也提供了一些程序式处理的&hellip;&hellip;&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">95页，Pattern r = Pattern.compile(&quot;^Sujbcet:(.*)&quot;,Pattern.CASE_INSENSITIVE);<br />其中的Sujbcet应写为Subject<br /></span></p>
<p><span style="color: rgb(255, 0, 0);">96页，第2段，&ldquo;Sun的package同时提供了程序式和面向对象式的处理方式是常见的做法&rdquo;应修改为&ldquo;Sun的package同时提供了程序式和面向对象式的处理方式，这是种常见的做法&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">96页，倒数第六行，&rdquo;出现NULL（而且可以用点号来匹配）。&ldquo;应修改为&rdquo;出现NUL（而且可以用点号来匹配）。&ldquo;<br /></span></p>
<p>111页，第1段，&ldquo;常见的例子是大写的&szlig;是两个字符的组合&ldquo;SS&rdquo;。这种情况只有Perl能够正确处理&rdquo;应修改为&ldquo;常见的例子是，大写的&szlig;由两个字符&ldquo;SS&rdquo;组合而成。这种情况只有Perl能够正确处理&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">114页，&ldquo;字符组及相关结构&rdquo;中，&ldquo;字符组缩略表示法&rdquo;应修改为&ldquo;字符组简记法&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">119页，第2行，&rdquo;范围内的所有字符&hellip;(例如，[0-9]与[908176354]是一样的。)&hellip;&ldquo;应修改为&rdquo;范围内的所有字符&hellip;(例如，[0-9]与[9081763542]是一样的。)&hellip;&ldquo;<br /></span></p>
<p><span style="color: rgb(255, 0, 0);">130页，3-11表名&ldquo;脚本语言中的行锚点&rdquo;应修改为&ldquo;若干语言中的行锚点&rdquo;</span></p>
<p>131页，第1段，&ldquo;如果结合上面那一点&rdquo;应修改为&ldquo;结合第一点&rdquo;</p>
<p>132页，第3段，&ldquo;但是这段程序的执行单位不是一次表达式而是一次匹配&rdquo;应修改为&ldquo;但是，循环的单位不是单个的表达式，而以一组表达式的匹配&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">134页，&ldquo;中间一级不过是&ldquo;语法（syntactic sugar）&rdquo;，表达方式更美观而已，&rdquo;应修改为&ldquo;中间一级不过是用起来更方便而已（syntactic sugar）&rdquo;</span><br style="color: rgb(255, 0, 0);" /><br /> 第4章</p>
<p>152页，倒数第1段，括号内，&ldquo;抑制自己的天性&rdquo;应修改为&ldquo;克制自己的本能&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">156 页，第3段，&ldquo;也就是说&ldquo;不到最后关头不能分胜负（It&rsquo;s not over until the fat lady sings）&rdquo;，但这段话又不符合本段的语境&rdquo;<br />应修改为<br />&ldquo;也就是说&ldquo;不到最后关头不能分胜负（It&rsquo;s not over until the fat lady sings）&rdquo;&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);"><span style="color: rgb(0, 0, 0);">156页 第3段 第2行</span><br style="color: rgb(0, 0, 0);" /><span style="color: rgb(0, 0, 0);">原文： 即使某个字表达式能够匹配</span><br style="color: rgb(0, 0, 0);" /><span style="color: rgb(0, 0, 0);">应改为：即使某个子表达式能够匹配</span></span></p>
<p><span style="color: rgb(255, 0, 0);"><span style="color: rgb(0, 0, 0);">160页 文字部分的 第5行<br />原文： 字符串的b之前（也就是当前的位置）匹配<br />应该为：字符串的c之前（也就是当前的位置）匹配</span><br /></span></p>
<p><span style="color: rgb(255, 0, 0);">172页，第2段，&ldquo;就可以命令正则引擎不必检查它们：</span><span style="color: rgb(255, 0, 0);">「^(?&gt;\w+)」</span><span style="color: rgb(255, 0, 0);">&rdquo;应修改为&ldquo;</span><span style="color: rgb(255, 0, 0);">就可以命令正则引擎不必检查它们：</span><span style="color: rgb(255, 0, 0);">「^(?&gt;\w+):」</span><span style="color: rgb(255, 0, 0);">&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">172页，最后一段，最后一个正则表达式(\.\d\d[1-9]?+)^\d+，应该修改为(\.\d\d[1-9]?+)\d+</p>
<p>173页，第一段，第2个正则表达式(?&gt;M)+应修改为(?&gt;M+)。<br /></span></p>
<p>第5章</p>
<p>188页 文字部分的 第4段 第2行 结尾<br />原文： 也不比担心<br />应该为：也不必担心</p>
<p>189页，倒数第9行，&quot;我们也把能把匹配三位数的多选分支放在最前面，这样&hellip;&quot;应修改为&quot;我们就把能把匹配三位数的多选分支放在最前面，这样&hellip;&quot;</p>
<p><span style="color: rgb(255, 0, 0);">191页，代码段中的注释大小写错误，&ldquo;#利用正则表达式检测wholePath&rdquo;应修改为&ldquo;#利用正则表达式检测WholePath&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">193页，第6行，&quot;算式中的括号。我们&hellip;想到┌\bfoo\([^])*\)┘，但这行不通。&quot;应修改为&quot;算式中的括号。我们&hellip;想到┌\bfoo\([^)]*\)┘，但这行不通。&quot;</span></p>
<p><span style="color: rgb(255, 0, 0);">194页，第5行，&rdquo;┌\[^()]*(\([^()]*\)[^()]*)*\)┘&ldquo;应修改为&quot;┌\([^()]*(\([^()]*\)[^()]*)*\)┘&quot;</span><br style="color: rgb(255, 0, 0);" /><br /> <span style="color: rgb(255, 0, 0);">195页，倒数第1段，&ldquo;虽然这个表达式比最开始的好得多&rdquo;应修改为&ldquo;虽然这个表达式比开头那个好一些&rdquo;</span></p>
<p>197页，第3段，&ldquo;所以，我们得用别的办法来解决&rdquo;应修改为&ldquo;所以，得想点别的办法&rdquo;</p>
<p>197页，第4段，&ldquo;仔细想想我们想要匹配的位于开始分隔符和结束分隔符之间的文本&rdquo;应修改为&ldquo;仔细想想要匹配的位于开始分隔符和结束分隔符之间的文本&rdquo;</p>
<p style="color: rgb(255, 0, 0);">197页，倒数第3段，&ldquo;如果回溯会导致不期望，与多选结构有关的匹配结果&rdquo;应修改为&ldquo;如果回溯会导致不期望的、与多选结构有关的匹配结果&rdquo;</p>
<p>199页，第5段，&ldquo;这个正则表达式曾被用作降解忽略优先量词的绝佳例子&rdquo;应修改为&ldquo;这个正则表达式曾被用作讲解忽略优先量词的绝佳例子&rdquo;<br /> <br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">199页，倒数第2段，&ldquo;但它并不正确（其实这三个表达式都不正确）&rdquo;应修改为&ldquo;但它并没有错（其实这三个表达式都没有错）&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">203页，标题&ldquo;检查HTTP URL&rdquo;应修改为&ldquo;校验HTTP URL&rdquo;，目录中也应同样修改</span></p>
<p><span style="color: rgb(255, 0, 0);">205页，代码段注释中，&ldquo;零个或多个据点分隔的部分&rdquo;应修改为&ldquo;零个或多个点号分隔的部分&rdquo;</span></p>
<p>210页 最后一行<br />原文：导致逆序环视（？！44）失败<br />应改为：导致否定顺序环视（？！44）失败</p>
<p>第6章</p>
<p>225页，第2段，&ldquo;对于没有转义字符的字符串来说，这样会一次读入整个字符串&rdquo;应修改为&ldquo;不包含转义字符的字符串，会被一次读入&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">228页，倒数第3行，&quot;从最后保存的状态开始回溯，在&ldquo;&hellip;anise&rdquo;处开始尝试&#8230;&quot;应修改为&quot;从最后保存的状态开始回溯，在&ldquo;&hellip;anese&rdquo;处开始尝试&#8230;&quot;</span><br /> <br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">233页，倒数第1段，&ldquo;所以，对这个例子来说，多选结构要比字符组快22倍左右&rdquo;应修改为&ldquo;所以，对这个例子来说，字符组比多选结构快22倍左右&rdquo;</span><br /> <br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">234页，第4段，&ldquo;新增的开销大约花费了5s的时间&rdquo;应修改为&ldquo;新增的开销大约是5秒&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">234页 正文部分第2行</span><br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">原文：现在，测试字符串只是上面的长度的1/1000，而测试需要进行1000次。</span><br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">应该为：现在，测试字符串只是上面的长度的1/1000，而测试需要进行1000000次。</span></p>
<p>246页，第1段，&ldquo;也能够减少传动装置真正应用正则表达式的位置&rdquo;应修改为&ldquo;也能减少传动装置真正应用正则表达式的次数&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">262页，倒数第12行，&rdquo;举例来说，如果目标&hellip;，那么使用的自表达式就是&hellip;&ldquo;应修改为&quot;举例来说，如果目标&hellip;，那么使用的正则表达式就是&hellip;&quot;</span></p>
<p style="color: rgb(255, 0, 0);">265页，第12行，&rdquo;┌(\{[^}]*\)| +)*┘(它永远不会终止)。或许&hellip;&ldquo;应修改为&quot;┌(\{[^}]*\}| +)*┘(它永远不会终止)。或许&hellip;&quot;</p>
<p style="color: rgb(255, 0, 0);">265页，第13行，表格中的&quot;Special&quot;应修改为&rdquo;special&quot;</p>
<p><span style="color: rgb(255, 0, 0);">265页，第14行，&ldquo; ┌\{[^]}*\}}&rdquo;应修改为&quot; ┌\{[^}]*\}┘&quot;</span></p>
<p><span style="color: rgb(255, 0, 0);">265页，第15行，&ldquo; 我们得到┌\{[^]}*\)┘*&rdquo;应修改为&quot; 我们得到┌\{[^}]*\)*&quot;</p>
<p>266页，第3行，&ldquo;┌ *(\{[^]}*\} *)*┘&rdquo;应修改为&ldquo;┌ *(\{[^}]*\} *)*┘&rdquo;</p>
<p>266页，倒数第2行，&ldquo;每次[^\\&quot;]+的匹配终止&hellip;&rdquo;应修改为&ldquo;每次┌[^\\&quot;]+┘的匹配终止&hellip;&rdquo;</span></p>
<p>266页，第3段，&ldquo;你就能把这几条推广开来&rdquo;应修改为&ldquo;就能把这几条推广开来&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">266页，倒数第4段，&ldquo;事实上，如果点号不能匹配换行符&rdquo;应修改为&ldquo;事实上，如果点号能够匹配换行符&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">269页，第1段，&ldquo;不会在匹配时陷入徒劳的尝试&rdquo;应修改为&ldquo;无法匹配时会陷入徒劳的尝试&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">271页，倒数第3行，&quot;现在处理$field&#8230;&quot;应修改为&ldquo;#现在处理$field&#8230;&rdquo;<br /></span></p>
<p><span style="color: rgb(255, 0, 0);">274页 上数第4行<br />原文：紧跟在x之后的斜线<br />改正：[^x]/ 是紧跟在不是x的字母后面的斜线<br /></span></p>
<p>第7章</p>
<p>293页，倒数第1段，&ldquo;动态作用域会临时&ldquo;保护&rdquo;全局变量&rdquo;应修改为&ldquo;动态作用域会把全局变量临时&ldquo;遮蔽&rdquo;起来&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">296页，倒数第2段，&ldquo;为方便起见，我们也可以给本地变量赋一个值 local($SomeVar)，这等于把undef赋值给$SomeVar&rdquo;应修改为&ldquo;为方便起见，我们也可以给 local($SomeVar)赋值，这等于给$SomeVar明确赋值，而不是使用undef&rdquo;</span></p>
<p>299页，第3段，&ldquo;分散在散落的 local、子程序和本地变量引用之间的复杂交互&rdquo;应修改为&ldquo;分布在散落的 local、子程序和本地变量引用之间的复杂交互&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">300页，正文第1段，&ldquo;你可以期望$ 的起点是开始尝试位置的文本,但它每次都是从整个字符串的开始位置开始的&rdquo;应修改为&ldquo;你可能认为$ 的起点是开始尝试位置的文本，其实它每次都是从整个字符串的开始位置开始的&rdquo;</span></p>
<p>301页，倒数第1段，&ldquo;明确设定的$1 等变量中，闭括号在最后&rdquo;应修改为&ldquo;明确设定的$1 等变量中，闭括号在最后的那对括号&rdquo;</p>
<p>308页，标题&ldquo;指定目标运算元&rdquo;应修改为&ldquo;指定匹配目标运算元&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">326页，第2段，&ldquo;split 没有返回的部分或全部的文本&rdquo;应修改为&ldquo;通常情况下split不会返回的部分或全部的文本&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">327页，标题&ldquo;嵌套代码结构&rdquo;应修改为&ldquo;内嵌代码结构&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">356页，第1段，&ldquo;不包含捕获型括号的正则表达式可以不必保存拷贝&rdquo;应修改为&ldquo;不包含捕获型括号的正则表达式可以不必保存副本&rdquo;</span></p>
<p>361页，第4段，&ldquo;这很适合检查单个的正则表达式的编译方法&rdquo;应修改为&ldquo;这很适合检查单个正则表达式的编译过程&rdquo;</p>
<p>第8章</p>
<p>365页，第5行，&ldquo;sjava.util.regex一经发布就给人留下了深刻印象&rdquo;应修改为&ldquo;java.util.regex一经发布就给人留下了深刻印象&rdquo;</p>
<p>367页，倒数第7行，&quot;\0octal要求开头为0，后接1到3位十进制数字。&quot;应修改为&quot;\0octal要求开头为0，后接1到3位八进制数字。&quot;</p>
<p><span style="color: rgb(255, 0, 0);">368页，表头，&quot;表8-3:java.util.regex 中Match和Regex的方法&quot;应修改为&quot;表8-3:java.util.regex 中Match和Regex的模式&quot;</span></p>
<p><span style="color: rgb(255, 0, 0);">368页，表8-3，&ldquo;Patern.UNIX_LINES&rdquo;应修改为&ldquo;Pattern.UNIX_LINES&rdquo;，&quot;Pattern.CANNON_EQ&quot;应修改为&quot;Pattern.CANON_EQ&quot;</span></p>
<p><span style="color: rgb(255, 0, 0);">368页，表8-3倒数第3行，&ldquo;对Unicode字符进行不区分大小写的匹配&rdquo;应修改为&ldquo;对非ASCII字符进行不区分大小写的匹配&rdquo;</span><br style="color: rgb(255, 0, 0);" /><br /> 369页，倒数第4段，&ldquo;Unicode block的支持要求使用&lsquo;In&rsquo;前缀&rdquo;应修改为&ldquo;Unicode区块的支持必须使用&lsquo;In&rsquo;前缀&rdquo;</p>
<p>371页，第2段，&ldquo;就我个人来说，更喜欢简称前两个为&ldquo;pattern&rdquo;和&ldquo;matcher&rdquo;&rdquo;应修改为&ldquo;我自己更喜欢把前两者简称为&ldquo;pattern&rdquo;和&ldquo;matcher&rdquo;&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">371页，第16行，&quot;IllegalAgumentException&quot;应修改为&ldquo;IllegalArgumentException&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">371页，倒数第4行，&quot;结果是&lsquo;matched [1st] from 12 to 15.&rsquo;。在本章的所有例子&hellip;&quot;应修改为&ldquo;结果是&lsquo;matched [1st] from 11 to 14.&rsquo;。在本章的所有例子&hellip;&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">373页，第1行，&ldquo;调用Patern.compile可能抛出两种类型的异常:如果&hellip;&rdquo;应修改为&ldquo;调用Pattern.compile可能抛出两种类型的异常:如果&hellip;&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">374页，第13行，&quot;&hellip;和hasTran-sparentBounds方法来修改和查询&hellip;&quot;应修改为&quot;&hellip;和hasTransparentBounds方法来修改和查询&hellip;&quot;</span></p>
<p>374页，倒数第6段，&ldquo;当前pattern的捕获型括号的数目&rdquo;应修改为&ldquo;当前pattern中捕获型括号的数目&rdquo;</p>
<p>377页 倒数第7行<br />原文：int end()<br />次方法返回整个匹配的终点的绝对偏移值<br />改为：此方法返回整个匹配的终点的绝对偏移值</p>
<p><span style="color: rgb(255, 0, 0);">377页，函数&ldquo;String gropu(int num)&rdquo;应修改为&ldquo;String group(int num)&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">377页，倒数第5行，&ldquo;MatcheResult toMatchResult()&rdquo;应修改为&ldquo;MatchResult toMatchResult()&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">377页，倒数第2行，&ldquo;如果前一次匹配不成功，或者&hellip;调用 toMatcheResult&rdquo;应修改为&ldquo;如果前一次匹配不成功，或者&hellip;调用 toMatchResult&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">378页，第5行<br />String regex = &quot;(?x) ^(https?):// ([^/:]+) (?:(\\ d+))?&quot;;<br />应修改为<br />String regex = &quot;(?x) ^(https?):// ([^/:]+) (?::(\\ d+))?&quot;;</span></p>
<p><span style="color: rgb(255, 0, 0);">378页倒数第3行，&ldquo;string.replaceAll(regex,replacement)&rdquo;应修改为&ldquo;String.replaceAll(regex,replacement)&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);"></span><span style="color: rgb(255, 0, 0);">388页，最后一段，&ldquo;即检索范围不等于整个目标字符串&rdquo;应修改为&ldquo;即使检索范围不等于整个目标字符串也是如此&rdquo;</span><br style="color: rgb(255, 0, 0);" /><br /> 389页，标题&ldquo;构建扫描程序&rdquo;应修改为&ldquo;构建扫描程序的方法&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">401页，倒数第6行，&quot;不断创建-回收 Mather&quot;应修改为&ldquo;不断创建-回收 Matcher&rdquo;</span></p>
<p>第9章</p>
<p><span style="color: rgb(255, 0, 0);">410页，第5段，&ldquo;即用即编译（On-The-Fly Compilation）&rdquo;应修改为&ldquo;直接编译（On-The-Fly Compilation）&rdquo;</span><br style="color: rgb(255, 0, 0);" /></p>
<p><span style="color: rgb(255, 0, 0);">410页，倒数第2段，&ldquo;来进行&ldquo;即用即编译&rdquo;的编译&rdquo;应修改为</span><span style="color: rgb(255, 0, 0);">&ldquo;来进行&ldquo;直接编译&rdquo;的编译&rdquo;<br /></span><br /> 432页，标题&ldquo;支持函数&rdquo;应修改为&ldquo;辅助函数&rdquo;</p>
<p>432页，倒数第4段，&ldquo;还有一些静态的支持函数&rdquo;应修改为&ldquo;还有一些静态辅助函数&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">438页，倒数第3段，&ldquo;尽管涌出并不大&rdquo;应修改为&ldquo;尽管用处并不大&rdquo;</span><br style="color: rgb(255, 0, 0);" /><br /> 第10章</p>
<p><span style="color: rgb(255, 0, 0);">442页，第3段，&ldquo;十进制转义只能接受两到三位八位数值&rdquo;应修改为&ldquo;八进制转义只能接受两到三位八进制数字&rdquo;</span><br style="color: rgb(255, 0, 0);" /><br /> 445页，倒数第5段，&ldquo;第448也给出了一个&ldquo;不好&rdquo;的原因&rdquo;应修改为&ldquo;第448页给出了一个&ldquo;不好&rdquo;的理由&rdquo;</p>
<p><span style="color: rgb(255, 0, 0);">455页，第3段，&ldquo;这就是默认的配列方式&rdquo;应修改为&ldquo;这就是默认的排列方式&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">459页，第3段，&ldquo;这个简单的例子把HTML中的bold tag全部转换为大写&rdquo;应修改为&ldquo;这个简单的例子在HTML中的所有大写单词两端加上bold tag&rdquo;</span><br style="color: rgb(255, 0, 0);" /><br style="color: rgb(255, 0, 0);" /><span style="color: rgb(255, 0, 0);">459页，倒数第4段，&ldquo;下面这个扩展的例子把bold tag里的单词变为小写&rdquo;应修改为&ldquo;下面这个扩展的例子在添加bold tag的同时把单词转换为小写&rdquo;</span></p>
<p><span style="color: rgb(255, 0, 0);">460页的表格，第三行开头应该为&ldquo;数组 数组&rdquo;，第四行开头应该为&ldquo;字符串 数组&rdquo;</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2007/09/14/1209937.aspx/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>《精通正则表达式》译者序</title>
		<link>http://blog.donews.com/maverick/archive/2007/08/31/1205082.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2007/08/31/1205082.aspx#comments</comments>
		<pubDate>Fri, 31 Aug 2007 01:38:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[敝帚自珍]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2007/08/31/1205082.aspx</guid>
		<description><![CDATA[《精通正则表达式（第3版）》（即Mastering Regular Expression，3rd Edition）是一本好书。]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.oreilly.com.cn/book.php?bn=978-7-121-04684-1">《精通正则表达式（第3版）》</a>（即Mastering Regular Expression，3rd Edition）是一本好书。<br /> 我还记得，自己刚开始工作时，就遇到了关于正则表达式的问题（从此被逼上梁山）：若从文本中抽取E-mail地址，还可以用字符串来查找（先定位到@，然 后向两端查找），若要抽取URL，简单的文本查找就无能为力了。正当我一筹莫展之时，项目经理说：&ldquo;可以用正则表达式，去网上找找资料吧。&rdquo;抱着这根救命 稻草，我搜索了之前只是听说过名字的正则表达式的资料，并打印了java.util.regex（开发用的Java）的文档来看。摸索了半天，我的感觉就 是，这玩意儿，真神奇，真复杂，真好用。<br /> 此后，用到正则表达式的地方越来越多，我也越来越感觉到它的重要，然而使用起来却总感觉捉襟见肘。当时是夏天，北京非常热，我决定下班之后不再着急赶车回家，而是在公司安心看看技术文档，于是邂逅了这本<a href="http://www.amazon.com/Mastering-Regular-Expressions-Jeffrey-Friedl/dp/0596528124/ref=sr_11_1/104-7541332-0393550?ie=UTF8&amp;qid=1184290193&amp;sr=11-1">Mastering Regular Expression</a>。该书原文是相当通畅易懂的，看完全书大概花了我一周的业余时间，之后便如拨云见日，感觉别有洞天&mdash;&mdash;原来正则表达式可以这样用，真是奇妙，真是令人拍案叫绝。<br /> 此后我运用正则表达式便不用再看什么资料了，充其量就是查查语言的具体文档，表达式的基本模型和思路，完全是在阅读本书时确立的。也正是因为细心阅读过本书，所以有时我能以正则表达式解决某些复杂的问题。我的朋友<a href="http://www.tinydust.net/prog/diary/diary.htm">郝培强</a>（Tinyfool， 昵称Tiny）曾问过我这样一个正则表达式的问题：在Apache服务器的Rewrite规则中，要求以一个正则表达式匹配&ldquo;除两个特定子域名之外的所有 其他子域名&rdquo;，其他人的办法都无法满足要求：要么只能匹配这两个特定的子域名，要么必须依赖程序分支才能进行判断。其实这个问题，是可以用一个正则表达式 匹配的。事后，Tiny说，看来，会用正则的人很多，但真正懂得正则的人很少。现实情况也确实如此，就我所见，不少同仁对正则表达式的运用，不外乎从网上 找一些现成的表达式，套用在自己的程序中，但对到底该用几个反斜线转义，转义是在字符串级别还是表达式级别进行的，捕获型括号是否必须，表达式的效率如 何，等等问题，往往都是一知半解，甚至毫无概念，在Tiny的问题面前，更是束手无策，一筹莫展。<br /> 就我个人来说，我所掌握的正则表达式的知识，绝大多数来自本书。正是依靠这些知识，我几乎能以正则表达式进行自己期望的任何文本处理，所以我相信，能够耐 心读完这本书的读者，一定能深入正则表达式的世界，若再加以练习和思考，就能熟练地依靠它解决各种复杂的问题（其中就包括类似Tiny的问题）了。<br /> 去年，通过<a href="http://blog.devep.net/virushuo/">霍炬（Virushuo）</a>的 介绍，我参加了博文视点的试译活动，很幸运地获得了翻译本书的机会。有机会与大家分享这样一本好书，我深感荣幸。500多页的书，拖拖拉拉，也花了半年多 的时间。虽然之前读过原著，积累了一些运用正则表达式的经验，也翻译过数十万字的资料，但要尽可能准确、贴切地传达原文的阅读感觉，我仍感颇费心力。部分 译文在确认理解原文的基础上，要以符合中文习惯的方式加以表述仍然颇费周折（例如，直译的&ldquo;正则表达式确实容许出现这种错误&rdquo;，原文的意思是&ldquo;这样的错误 超出了正则表达式的能力&rdquo;，最后修改为&ldquo;出现这样的错误，不能怪正则表达式&rdquo;或&ldquo;这样的问题，错不在正则表达式&rdquo;）。另有部分词语，虽可译为中文，但为保 证阅读的流畅，没有翻译（例如，&ldquo;它包含特殊和一般两个部分，特殊部分之所以是特殊的，原因在于&hellip;&hellip;&rdquo;，此处special和normal是专指，故翻译 为&ldquo;它包含special和normal两个部分，special部分之所以得名，原因在于&hellip;&hellip;&rdquo;），这样的处理，相信不会影响读者的理解。<br /> 在本书翻译结束之际，我首先要感谢霍炬，他的引荐让我获得了翻译这本书的机会；还要感谢博文视点的周筠老师，她谨慎严格的工作态度，时刻提醒我不能马虎对待这本经典之作；还有本书的责编晓菲，她为本书的编辑和校对做了大量细致而深入的工作。<br /> 另外我还要感谢东北师范大学文学院的王确老师，在我求学期间，王老师给予我诸多指点，离校时间愈长，愈是怀念和庆幸那段经历，可以说，没有与他的相识，便没有我的今天。<br /> 本书是讲授正则表达式的经典之作，翻译过程中，我虽力求把握原文，语言通畅，但翻译中的错误或许是在所难免的，对此本人愿负全部责任。希望广大读者发现错 误能及时与我和出版社联系以便再版时修正，或是以勘误的形式公布出来以惠及其他读者。如果读者有任何想法或建议，欢迎给我写信，我的邮件地址是： yusheng.regex@gmail.com。</p>
<p><span id="more-193"></span><br /> 如今正则表达式已经成为几乎所有主流编程语言中的必备元素：Java、Perl、Python、PHP、Ruby&hellip;&hellip;莫不如此，甚至功能稍强大一些的文本 编辑工具，都支持正则表达式。尤其是在Web兴起之后，开发任务中的一大部分甚至全部，都是对字符串的处理。相比简单的字符串比较、查找、替换，正则表达 式提供了强大得多的处理能力（最重要的是，它能够处理&ldquo;符合某种抽象模式&rdquo;的字符串，而不是固化的、具体的字符串）。熟练运用它们，能够节省大量的开发时 间，甚至解决一些之前看来是mission impossible的问题。<br /> 本书是讲解正则表达式的经典之作。其他介绍正则表达式的资料，往往局限于具体的语法和函数的讲解，于语法细节处着墨太多，忽略了正则表达式本身。这样，读 者虽然对关于正则表达式的具体规定有所了解，但终究是只见树木不见森林，遇上复杂的情况，往往束手无策，举步维艰。而本书自第1版开始便着力于教会读者 &ldquo;以正则表达式来思考（think regular expression）&rdquo;，向读者讲授正则表达式的精髓（正则表达式的各种流派、匹配原理、优化原则，等等），而不拘泥于具体的规定和形式。了解这些精 髓，再辅以具体操作的文档，读者便可做到&ldquo;胸中有丘壑，下笔如有神&rdquo;；即便问题无法以正则表达式来解决，读者也能很快作出判断，而不必盲目尝试，徒费工 夫。<br /> 不了解正则表达式的读者，可循序渐进，依次阅读各章，即便之前完全未接触过正则表达式，读过前两章，也能在心中描绘出概略的图谱。第3、4、5、6章是本 书的重点，也是核心价值所在，它们分别介绍了正则表达式的特性和流派、匹配原理、实用诀窍以及调校措施。这样的知识与具体语言无关，适用于几乎所有的语言 和工具（当然，如果使用DFA引擎，第6章的价值要打些折扣），所谓&ldquo;大象无形&rdquo;，便是如此。读者如能仔细研读，悉心揣摩，之后解决各种问题时，必定获益 匪浅。第7、8、9、10章分别讲解了Perl、Java、.NET、PHP中正则表达式的用法，看来类似参考手册，其实是对前面4章知识的包装，将抽象 的知识辅以具体的语言规定，以具体的形式表现出来。所以，心急的读者，在阅读这些章节之前，最好先通读第3、4、5、6章，以便更好地理解其中的逻辑和思 路。<br /> 相信仔细阅读完本书的读者，定会有登堂入室的感觉。不但能见识到正则表达式各种令人眼花缭乱的特性，更能够深入了解表达式、匹配、引擎背后的原理，从而写出复杂、神奇而又高效的正则表达式，快速地解决工作中的各种问题。</p>
<p>余晟<br /> 2007年6月于北京</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2007/08/31/1205082.aspx/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>开发笔记：关于一个函数的讨论</title>
		<link>http://blog.donews.com/maverick/archive/2007/08/21/1201383.aspx</link>
		<comments>http://blog.donews.com/maverick/archive/2007/08/21/1201383.aspx#comments</comments>
		<pubDate>Tue, 21 Aug 2007 08:42:00 +0000</pubDate>
		<dc:creator>李卫公</dc:creator>
				<category><![CDATA[开发]]></category>

		<guid isPermaLink="false">http://blog.donews.com/maverick/archive/2007/08/21/1201383.aspx</guid>
		<description><![CDATA[朋友问这样的问题：
写了一个函数，从网页源代码中抽取一个结点的文本，函数本身没有问题，但同事在code review时指出，如果提取不成功，应该返回None，而不是空字符串""。

提问的朋友跟我说：你之前说过，从数据库里取出一批数据，如果不存在，要返回一个空的Collection，而不是None（这样才能正确表示“需要的数据不存在”），那么这里，是否应该听取同事的意见呢？
当时我的回答是，因为从这个函数接受数据的代码期望获得的是一个字符串，所以，如果提取不成功，应该返回""。
但是，这样，就无法区分下面两种情况了：存在这个结点，但是一个空结点；不存在这个结点。

这几天晚上一直在思考这个问题，并与Patrick讨论，最后的结论是：]]></description>
			<content:encoded><![CDATA[<p>朋友问这样的问题：<br />写了一个函数，从网页源代码中抽取一个结点的文本，函数本身没有问题，但同事在code review时指出，如果提取不成功，应该返回None，而不是空字符串&quot;&quot;。</p>
<p>提问的朋友跟我说：你之前说过，从数据库里取出一批数据，如果不存在，要返回一个空的Collection，而不是None（这样才能正确表示&ldquo;需要的数据不存在&rdquo;），那么这里，是否应该听取同事的意见呢？<br />当时我的回答是，因为从这个函数接受数据的代码期望获得的是一个字符串，所以，如果提取不成功，应该返回&quot;&quot;。<br />但是，这样，就无法区分下面两种情况了：存在这个结点，但是一个空结点；不存在这个结点。</p>
<p>这几天晚上一直在思考这个问题，并与<a href="http://blog.csdn.net/holy_phoenix">Patrick</a>讨论，最后的结论是：<br />之所以会出现这个问题，原因在于函数的定义是不明确的&mdash;&mdash;虽然函数名看来很清楚，但它的意义是不确定的。<br />按照<a href="http://blog.donews.com/maverick/archive/2006/04/22/841290.aspx">契约式设计(Design by Contract)</a>的原则，每个模块都应该有前驱条件(pre-condition)和后继条件(post-condition)。正是因为两位开发人员对这一点的认识存在分歧，问题才会出现：</p>
<ul>
<li>如果这个函数的前驱条件是，必须提供一段包含此结点的源代码（也就是说，这个结点必须存在），就不能返回None，返回&quot;&quot;，就表示这个结点内容为空，如果提供的源代码不包含这个结点，应抛出异常；</li>
<li>如果前驱条件是，提供的源代码不必包含这个结点，那么，这个函数其实就履行了两项职责&mdash;&mdash;检查是否存在结点，以及提取结点的文本，必须与调用方有一个约定，来表示这两重含义（此时可以用None表示&ldquo;不存在结点&rdquo;的情况，用&quot;&quot;表示结点内容为空的情况，当然我不推荐这么做）。</li>
</ul>
<p>同样，按照契约式设计的原则，数据验证的职责在调用方，也就是说，约定了这个函数的前驱和后继条件之后，调用方在调用之前，必须保证前驱条件：如果函数要求源代码必须包含这个结点，那么验证是否存在的职责就应该由调用方来承担。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/maverick/archive/2007/08/21/1201383.aspx/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

