<?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>我爱正则表达式 &#187; 教程</title>
	<atom:link href="http://iregex.org/blog/category/tutorial/feed" rel="self" type="application/rss+xml" />
	<link>http://iregex.org</link>
	<description>原创、翻译、转载关于正则表达式的文章</description>
	<lastBuildDate>Sun, 27 Jun 2010 04:20:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/><atom:link rel="hub" href="http://www.feedsky.com/api/RPC2"/><atom:link rel="hub" href="http://blogsearch.google.com/ping/RPC2"/><atom:link rel="hub" href="http://blog.yodao.com/ping/RPC2"/><atom:link rel="hub" href="http://www.feedsky.com/api/RPC2"/><atom:link rel="hub" href="http://www.xianguo.com/xmlrpc/ping.php"/><atom:link rel="hub" href="http://www.zhuaxia.com/rpc/server.php"/><atom:link rel="hub" href="http://rpc.technorati.com/rpc/ping"/><atom:link rel="hub" href="http://rpc.pingomatic.com/"/>	
<!-- Start Of Script Generated By WP-PostViews Plus -->
<script type='text/javascript' src='http://iregex.org/wp-includes/js/jquery/jquery.js?ver=1.4.2'></script>
<script type="text/javascript">
/* <![CDATA[ */
/* ]]> */
</script>
<!-- End Of Script Generated By WP-PostViews Plus -->
	<item>
		<title>Python 中文正则笔记</title>
		<link>http://iregex.org/blog/python-chinese-unicode-regular-expressions.html</link>
		<comments>http://iregex.org/blog/python-chinese-unicode-regular-expressions.html#comments</comments>
		<pubDate>Sun, 27 Jun 2010 03:50:41 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[chinese]]></category>
		<category><![CDATA[cjk]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=129</guid>
		<description><![CDATA[总结在 python 语言里使用正则表达式匹配中文的经验。关键词：中文，cjk，utf8，unicode，python。 从字符串的角度来说，中文不如英文整齐、规范，这是不可避免的现实。本文结合网上资料以及个... ]]></description>
			<content:encoded><![CDATA[<p>总结在 python 语言里使用正则表达式匹配中文的经验。关键词：中文，cjk，utf8，unicode，python。</p>
<p><span id="more-129"></span></p>
<p>从字符串的角度来说，中文不如英文整齐、规范，这是不可避免的现实。本文结合网上资料以及个人经验，以 python 语言为例，稍作总结。欢迎补充或挑错。</p>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">一点经验</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<ul>
<li>可以使用 <code class="codecolorer python default"><span class="python"><span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code>函数查看字串的原始格式。这对于写正则表达式有所帮助。
            </li>
<li>Python 的 <code class="codecolorer python default"><span class="python"><span style="color: #dc143c;">re</span></span></code>模块有两个相似的函数：<code class="codecolorer python default"><span class="python"><span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span></span></code> 。两个函数的匹配过程完全一致，只是起点不同。<code class="codecolorer python default"><span class="python">match</span></code>只从字串的开始位置进行匹配，如果失败，它就此放弃；而<code class="codecolorer python default"><span class="python">search</span></code>则会锲而不舍地完全遍历整个字串中所有可能的位置，直到成功地找到一个匹配，或者搜索完字串，以失败告终。如果你了解<code class="codecolorer python default"><span class="python">match</span></code>的特性（在某些情况下比较快），大可以自由用它；如果不太清楚，<code class="codecolorer python default"><span class="python">search</span></code>通常是你需要的那个函数。</li>
<li>从一堆文本中，找出所有可能的匹配，以列表的形式返回，这种情况用<code class="codecolorer python default"><span class="python">findall<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code>这个函数。例子见后面的代码。</li>
<li><code class="codecolorer python default"><span class="python">utf8</span></code>下，每个汉字占据3个字符位置，正则式为<code class="codecolorer python default"><span class="python"><span style="color: black;">&#91;</span>\x80-\xff<span style="color: black;">&#93;</span><span style="color: black;">&#123;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#125;</span></span></code>，这个都知道了吧。</li>
<li><code class="codecolorer python default"><span class="python"><span style="color: #008000;">unicode</span></span></code>下，汉字的格式如<code class="codecolorer python default"><span class="python">\uXXXX</span></code>，只要找到对应的字符集的范围，就能匹配相应的字串，方便从多语言文本中挑出所需要的某种语言的文本。不过，对于像日文这样的粘着语，既有中文字符，又有平假名片假名，或许结果会有所偏差。</li>
<li>两种字符类可以并列在一起使用，例如，平假名、片假名、中文的放在一起，<code class="codecolorer python default"><span class="python">u<span style="color: #483d8b;">&quot;[<span style="color: #000099; font-weight: bold;">\u</span>4e00-<span style="color: #000099; font-weight: bold;">\u</span>9fa5<span style="color: #000099; font-weight: bold;">\u</span>3040-<span style="color: #000099; font-weight: bold;">\u</span>309f<span style="color: #000099; font-weight: bold;">\u</span>30a0-<span style="color: #000099; font-weight: bold;">\u</span>30ff]+&quot;</span></span></code>，来自定义所需要匹配的文本。</li>
<li>匹配中文时，正则表达式和目标字串的格式必须相同。这一点至关重要。或者都用默认的<code class="codecolorer python default"><span class="python">utf8</span></code>，此时你不用额外做什么；如果是<code class="codecolorer python default"><span class="python"><span style="color: #008000;">unicode</span></span></code>，就需要在正则式之前加上<code class="codecolorer python default"><span class="python">u<span style="color: #483d8b;">&quot;&quot;</span></span></code>格式。</li>
<li>可以这样定义<code class="codecolorer python default"><span class="python"><span style="color: #008000;">unicode</span></span></code>字符串：<code class="codecolorer python default"><span class="python"><span style="color: #dc143c;">string</span>=u<span style="color: #483d8b;">&quot;我爱正则表达式&quot;</span></span></code>。如果字串不是<code class="codecolorer python default"><span class="python"><span style="color: #008000;">unicode</span></span></code>的，可以使用<code class="codecolorer python default"><span class="python"><span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></span></code>函数转换之。如果你知道源字串的编码，可以使用<code class="codecolorer python default"><span class="python">newstr=<span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>oldstring, original_coding_name<span style="color: black;">&#41;</span></span></code>的方式转换，例如 linux 下常用<code class="codecolorer python default"><span class="python"><span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">string</span>, <span style="color: #483d8b;">&quot;utf8&quot;</span><span style="color: black;">&#41;</span></span></code>，windows 下或许会用<code class="codecolorer python default"><span class="python">cp936</span></code>吧，没测试。</li>
</ul>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">例程序</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<div class="codecolorer-container python mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span><br />
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span><br />
<span style="color: #808080; font-style: italic;">#</span><br />
<span style="color: #808080; font-style: italic;">#author: &nbsp; &nbsp; &nbsp; &nbsp; rex</span><br />
<span style="color: #808080; font-style: italic;">#blog: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://iregex.org</span><br />
<span style="color: #808080; font-style: italic;">#filename &nbsp; &nbsp; &nbsp; &nbsp;py_utf8_unicode.py</span><br />
<span style="color: #808080; font-style: italic;">#created: &nbsp; &nbsp; &nbsp; &nbsp;2010-06-27 09:11</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span><br />
<span style="color: #ff7700;font-weight:bold;">def</span> findPart<span style="color: black;">&#40;</span>regex, text, name<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; res=<span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span>regex, text<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> res:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;There are %d %s parts:<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span>, name<span style="color: black;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> r <span style="color: #ff7700;font-weight:bold;">in</span> res:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span>,r<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span><br />
<br />
<span style="color: #808080; font-style: italic;">#sample is utf8 by default.</span><br />
sample=<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'en: Regular expression is a powerful tool for manipulating text.<br />
zh: 正则表达式是一种很有用的处理文本的工具。<br />
jp: 正規表現は非常に役に立つツールテキストを操作することです。<br />
jp-char: あアいイうウえエおオ<br />
kr:정규 표현식은 매우 유용한 도구 텍스트를 조작하는 것입니다.<br />
puc: 。？！、，；：“ ”‘ ’——……·－·《》〈〉！￥％＆＊＃<br />
'</span><span style="color: #483d8b;">''</span><br />
<span style="color: #808080; font-style: italic;">#let's look its raw representation under the hood:</span><br />
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;the raw utf8 string is:<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span>sample<span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">print</span> <br />
<br />
<span style="color: #808080; font-style: italic;">#find the non-ascii chars:</span><br />
findPart<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;[<span style="color: #000099; font-weight: bold;">\x</span>80-<span style="color: #000099; font-weight: bold;">\x</span>ff]+&quot;</span>,sample,<span style="color: #483d8b;">&quot;non-ascii&quot;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">#convert the utf8 to unicode</span><br />
usample=<span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>sample,<span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">#let's look its raw representation under the hood:</span><br />
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;the raw unicode string is:<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span>usample<span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">print</span> <br />
<br />
<span style="color: #808080; font-style: italic;">#get each language parts:</span><br />
findPart<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;[<span style="color: #000099; font-weight: bold;">\u</span>4e00-<span style="color: #000099; font-weight: bold;">\u</span>9fa5]+&quot;</span>, usample, <span style="color: #483d8b;">&quot;unicode chinese&quot;</span><span style="color: black;">&#41;</span><br />
findPart<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;[<span style="color: #000099; font-weight: bold;">\u</span>ac00-<span style="color: #000099; font-weight: bold;">\u</span>d7ff]+&quot;</span>, usample, <span style="color: #483d8b;">&quot;unicode korean&quot;</span><span style="color: black;">&#41;</span><br />
findPart<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;[<span style="color: #000099; font-weight: bold;">\u</span>30a0-<span style="color: #000099; font-weight: bold;">\u</span>30ff]+&quot;</span>, usample, <span style="color: #483d8b;">&quot;unicode japanese katakana&quot;</span><span style="color: black;">&#41;</span><br />
findPart<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;[<span style="color: #000099; font-weight: bold;">\u</span>3040-<span style="color: #000099; font-weight: bold;">\u</span>309f]+&quot;</span>, usample, <span style="color: #483d8b;">&quot;unicode japanese hiragana&quot;</span><span style="color: black;">&#41;</span> <br />
findPart<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;[<span style="color: #000099; font-weight: bold;">\u</span>3000-<span style="color: #000099; font-weight: bold;">\u</span>303f<span style="color: #000099; font-weight: bold;">\u</span>fb00-<span style="color: #000099; font-weight: bold;">\u</span>fffd]+&quot;</span>, usample, <span style="color: #483d8b;">&quot;unicode cjk Punctuation&quot;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>其输出结果为：</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">the raw utf8 string is:<br />
'en: Regular expression is a powerful tool for manipulating text.\nzh: \xe6\xad\xa3\xe5\x88\x99\xe8\xa1\xa8\xe8\xbe\xbe\xe5\xbc\x8f\xe6\x98\xaf\xe4\xb8\x80\xe7\xa7\x8d\xe5\xbe\x88\xe6\x9c\x89\xe7\x94\xa8\xe7\x9a\x84\xe5\xa4\x84\xe7\x90\x86\xe6\x96\x87\xe6\x9c\xac\xe7\x9a\x84\xe5\xb7\xa5\xe5\x85\xb7\xe3\x80\x82\njp: \xe6\xad\xa3\xe8\xa6\x8f\xe8\xa1\xa8\xe7\x8f\xbe\xe3\x81\xaf\xe9\x9d\x9e\xe5\xb8\xb8\xe3\x81\xab\xe5\xbd\xb9\xe3\x81\xab\xe7\xab\x8b\xe3\x81\xa4\xe3\x83\x84\xe3\x83\xbc\xe3\x83\xab\xe3\x83\x86\xe3\x82\xad\xe3\x82\xb9\xe3\x83\x88\xe3\x82\x92\xe6\x93\x8d\xe4\xbd\x9c\xe3\x81\x99\xe3\x82\x8b\xe3\x81\x93\xe3\x81\xa8\xe3\x81\xa7\xe3\x81\x99\xe3\x80\x82\njp-char: \xe3\x81\x82\xe3\x82\xa2\xe3\x81\x84\xe3\x82\xa4\xe3\x81\x86\xe3\x82\xa6\xe3\x81\x88\xe3\x82\xa8\xe3\x81\x8a\xe3\x82\xaa\nkr:\xec\xa0\x95\xea\xb7\x9c \xed\x91\x9c\xed\x98\x84\xec\x8b\x9d\xec\x9d\x80 \xeb\xa7\xa4\xec\x9a\xb0 \xec\x9c\xa0\xec\x9a\xa9\xed\x95\x9c \xeb\x8f\x84\xea\xb5\xac \xed\x85\x8d\xec\x8a\xa4\xed\x8a\xb8\xeb\xa5\xbc \xec\xa1\xb0\xec\x9e\x91\xed\x95\x98\xeb\x8a\x94 \xea\xb2\x83\xec\x9e\x85\xeb\x8b\x88\xeb\x8b\xa4.\npuc: \xe3\x80\x82\xef\xbc\x9f\xef\xbc\x81\xe3\x80\x81\xef\xbc\x8c\xef\xbc\x9b\xef\xbc\x9a\xe2\x80\x9c \xe2\x80\x9d\xe2\x80\x98 \xe2\x80\x99\xe2\x80\x94\xe2\x80\x94\xe2\x80\xa6\xe2\x80\xa6\xc2\xb7\xef\xbc\x8d\xc2\xb7\xe3\x80\x8a\xe3\x80\x8b\xe3\x80\x88\xe3\x80\x89\xef\xbc\x81\xef\xbf\xa5\xef\xbc\x85\xef\xbc\x86\xef\xbc\x8a\xef\xbc\x83\n'<br />
<br />
There are 14 non-ascii parts:<br />
<br />
&nbsp; &nbsp; 正则表达式是一种很有用的处理文本的工具。<br />
&nbsp; &nbsp; 正規表現は非常に役に立つツールテキストを操作することです。<br />
&nbsp; &nbsp; あアいイうウえエおオ<br />
&nbsp; &nbsp; 정규<br />
&nbsp; &nbsp; 표현식은<br />
&nbsp; &nbsp; 매우<br />
&nbsp; &nbsp; 유용한<br />
&nbsp; &nbsp; 도구<br />
&nbsp; &nbsp; 텍스트를<br />
&nbsp; &nbsp; 조작하는<br />
&nbsp; &nbsp; 것입니다<br />
&nbsp; &nbsp; 。？！、，；：“<br />
&nbsp; &nbsp; ”‘<br />
&nbsp; &nbsp; ’——……·－·《》〈〉！￥％＆＊＃<br />
<br />
the raw unicode string is:<br />
u'en: Regular expression is a powerful tool for manipulating text.\nzh: \u6b63\u5219\u8868\u8fbe\u5f0f\u662f\u4e00\u79cd\u5f88\u6709\u7528\u7684\u5904\u7406\u6587\u672c\u7684\u5de5\u5177\u3002\njp: \u6b63\u898f\u8868\u73fe\u306f\u975e\u5e38\u306b\u5f79\u306b\u7acb\u3064\u30c4\u30fc\u30eb\u30c6\u30ad\u30b9\u30c8\u3092\u64cd\u4f5c\u3059\u308b\u3053\u3068\u3067\u3059\u3002\njp-char: \u3042\u30a2\u3044\u30a4\u3046\u30a6\u3048\u30a8\u304a\u30aa\nkr:\uc815\uaddc \ud45c\ud604\uc2dd\uc740 \ub9e4\uc6b0 \uc720\uc6a9\ud55c \ub3c4\uad6c \ud14d\uc2a4\ud2b8\ub97c \uc870\uc791\ud558\ub294 \uac83\uc785\ub2c8\ub2e4.\npuc: \u3002\uff1f\uff01\u3001\uff0c\uff1b\uff1a\u201c \u201d\u2018 \u2019\u2014\u2014\u2026\u2026\xb7\uff0d\xb7\u300a\u300b\u3008\u3009\uff01\uffe5\uff05\uff06\uff0a\uff03\n'<br />
<br />
There are 6 unicode chinese parts:<br />
<br />
&nbsp; &nbsp; 正则表达式是一种很有用的处理文本的工具<br />
&nbsp; &nbsp; 正規表現<br />
&nbsp; &nbsp; 非常<br />
&nbsp; &nbsp; 役<br />
&nbsp; &nbsp; 立<br />
&nbsp; &nbsp; 操作<br />
<br />
There are 8 unicode korean parts:<br />
<br />
&nbsp; &nbsp; 정규<br />
&nbsp; &nbsp; 표현식은<br />
&nbsp; &nbsp; 매우<br />
&nbsp; &nbsp; 유용한<br />
&nbsp; &nbsp; 도구<br />
&nbsp; &nbsp; 텍스트를<br />
&nbsp; &nbsp; 조작하는<br />
&nbsp; &nbsp; 것입니다<br />
<br />
There are 6 unicode japanese katakana parts:<br />
<br />
&nbsp; &nbsp; ツールテキスト<br />
&nbsp; &nbsp; ア<br />
&nbsp; &nbsp; イ<br />
&nbsp; &nbsp; ウ<br />
&nbsp; &nbsp; エ<br />
&nbsp; &nbsp; オ<br />
<br />
There are 11 unicode japanese hiragana parts:<br />
<br />
&nbsp; &nbsp; は<br />
&nbsp; &nbsp; に<br />
&nbsp; &nbsp; に<br />
&nbsp; &nbsp; つ<br />
&nbsp; &nbsp; を<br />
&nbsp; &nbsp; することです<br />
&nbsp; &nbsp; あ<br />
&nbsp; &nbsp; い<br />
&nbsp; &nbsp; う<br />
&nbsp; &nbsp; え<br />
&nbsp; &nbsp; お<br />
<br />
There are 5 unicode cjk Punctuation parts:<br />
<br />
&nbsp; &nbsp; 。<br />
&nbsp; &nbsp; 。<br />
&nbsp; &nbsp; 。？！、，；：<br />
&nbsp; &nbsp; －<br />
&nbsp; &nbsp; 《》〈〉！￥％＆＊＃</div></td></tr></tbody></table></div>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/python-chinese-unicode-regular-expressions.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Superor老师的正则表达式视频教程</title>
		<link>http://iregex.org/blog/regex-tutorial-by-superor.html</link>
		<comments>http://iregex.org/blog/regex-tutorial-by-superor.html#comments</comments>
		<pubDate>Sun, 20 Jun 2010 01:35:06 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=127</guid>
		<description><![CDATA[浏览CU时发现Superor老师的《探索Perl的世界(更新到40集)-Perl 教学视频》（国人，中文），其中有5集是讲正则表达式的。观看之后觉得不错，贴在这里。 之前贴过余晟老师的正则表达式视频，由... ]]></description>
			<content:encoded><![CDATA[<p>浏览CU时发现Superor老师的《<a href="http://bbs.chinaunix.net/thread-1707137-1-2.html">探索Perl的世界(更新到40集)-Perl 教学视频</a>》（国人，中文），其中有5集是讲正则表达式的。观看之后觉得不错，贴在这里。<span id="more-127"></span></p>
<p>之前贴过余晟老师的正则表达式视频，由于各种不可抗力，所上传到各大空间的，也都渐渐不再能访问。我最早是从老友牛腩粉那里得到的，地址<a href="http://tieba.baidu.com/f?kz=464065073">在此</a>，可以留言，碰碰运气。</p>
<p>Superor老师的视频，其实不限于正则表达式，而是系统地讲解 Perl 的教程。我是断章取义，将正则表达式部分摘过来了。Superor老师也说过了，他在学习Perl时，准备了不少书，但是不是系统地看完，而是用到哪一部分，就细读这一部分的全部内容。学正则表达式也可如此。</p>
<p>视频是在线的，效果不错，虽然会插播广告。</p>
<p>第20集：第八章 正则表达式<br /> <br />
<a href="http://www.boobooke.com/v/bbk3748" target="_blank">http://www.boobooke.com/v/bbk3748</a></p>
<p>第21集：第八章 正则表达式<br /> <br />
<a href="http://www.boobooke.com/v/bbk3749" target="_blank">http://www.boobooke.com/v/bbk3749</a></p>
<p>第22集：第八章 正则表达式<br /> <br />
<a href="http://www.boobooke.com/v/bbk3750" target="_blank">http://www.boobooke.com/v/bbk3750</a></p>
<p>第23集：第八章 正则表达式<br /> <br />
<a href="http://www.boobooke.com/v/bbk3751" target="_blank">http://www.boobooke.com/v/bbk3751</a></p>
<p>第24集：第八章 正则表达式<br /> <br />
<a href="http://www.boobooke.com/v/bbk3752" target="_blank">http://www.boobooke.com/v/bbk3752</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/regex-tutorial-by-superor.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>小议“排除型匹配”</title>
		<link>http://iregex.org/blog/negate-match.html</link>
		<comments>http://iregex.org/blog/negate-match.html#comments</comments>
		<pubDate>Mon, 24 May 2010 08:46:29 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[问答]]></category>
		<category><![CDATA[exclude]]></category>
		<category><![CDATA[lookaround]]></category>
		<category><![CDATA[negate]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=122</guid>
		<description><![CDATA[网友cfc4n问及关于(?!)的正则表达式问题。回答之后，顺便总结了一下Perl语言中如何匹配“不出现”某元素，贴在这里。 问题 问题描述 有如下文本，如何使用正则式，将其中不含color选项的item... ]]></description>
			<content:encoded><![CDATA[<p>网友cfc4n问及关于(?!)的正则表达式问题。回答之后，顺便总结了一下Perl语言中如何匹配“不出现”某元素，贴在这里。<span id="more-122"></span></p>
<h2 style="background-color: rgb(153, 204, 0); border: 1px solid rgb(102, 102, 102); color: rgb(0, 0, 0); font-size: 21px; line-height: 35px; padding-top: 3px; text-indent: 6px;">问题</h2>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">问题描述</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>
    有如下文本，如何使用正则式，将其中<b>不含color选项的item</b>匹配出来？</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;item&gt;<br />
&nbsp; &nbsp; color:red;<br />
&lt;/item&gt;<br />
&lt;item&gt;<br />
&nbsp; &nbsp; size:12;<br />
&nbsp; &nbsp; number:45;<br />
&nbsp; &nbsp; type:good;<br />
&lt;/item&gt;</div></td></tr></tbody></table></div>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">典型的错误答案</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<p>新手容易提供这样的错误答案：<code class="codecolorer perl default"><span class="perl"><span style="color: #009999;">&lt;item&gt;</span><span style="color: #339933;">.*?</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>color<span style="color: #009900;">&#41;</span><span style="color: #339933;">.*?&lt;/</span>item<span style="color: #339933;">&gt;</span></span></code>。其出发点是正确的：只有当color不出现在目标字串时，该匹配才是所需要的。事实上，这样的正则表达式不能如君所愿，它匹配所有的<code class="codecolorer text default"><span class="text">&lt;item&gt;...&lt;/item&gt;</span></code>。这是为什么呢？</p>
</blockquote>
</blockquote>
<h2 style="background-color: rgb(153, 204, 0); border: 1px solid rgb(102, 102, 102); color: rgb(0, 0, 0); font-size: 21px; line-height: 35px; padding-top: 3px; text-indent: 6px;">Perl之排除型匹配</h2>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">最简单的排除型匹配</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<p>匹配是<code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">=~</span></span></code>, 不匹配当然是 <code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">!~</span></span></code> 了。写到这里想到，在正则式中，凡是由<code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">=</span></span></code>组成的正则式符号，全可以使用<code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">!</span></span></code>来替代，以表现相反的意思。例如<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?=</span><span style="color: #009900;">&#41;</span></span></code>与<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span><span style="color: #009900;">&#41;</span></span></code>，<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?&lt;=</span><span style="color: #009900;">&#41;</span></span></code>与<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?&lt;!</span><span style="color: #009900;">&#41;</span></span></code>，<code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">=~</span></span></code>与<code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">!~</span></span></code>。</p>
<p>返回正题，看个例子。如果要检测某字串是否含有good，当然要用<code class="codecolorer perl default"><span class="perl"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$string</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/good/</span><span style="color: #009900;">&#41;</span></span></code>，如果<code class="codecolorer perl default"><span class="perl"><span style="color: #0000ff;">$string</span></span></code>里有good则条件为真，否则为假；</p>
<p>如果要检测某字串是否<b>不</b>含有good，可以用<code class="codecolorer perl default"><span class="perl"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$string</span> <span style="color: #339933;">!~</span> <span style="color: #009966; font-style: italic;">/good/</span><span style="color: #009900;">&#41;</span></span></code>，如果<code class="codecolorer perl default"><span class="perl"><span style="color: #0000ff;">$string</span></span></code>里没有good则条件为真，否则为假。</p>
<p>这种匹配测试，较适合于在大段的字串中搜索某个简单的模式，然后对于匹配的结果作出两种不同的判断，非此即彼。虽然迅速干练，但是对于复杂情况的判断，还是有些累赘。</p>
<p>对于文章开始提出的问题而言，当然可以这样解决：先搜索所有的 <code class="codecolorer text default"><span class="text">&lt;item&gt;...&lt;/item&gt;</span></code>，然后分别判断是否存在color项即可：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl -w</span><br />
<br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$text</span><span style="color: #339933;">=</span><span style="color: #cc0000; font-style: italic;">&lt;&lt;END;<br />
&lt;item&gt;<br />
&nbsp; &nbsp; color:red;<br />
&lt;/item&gt;<br />
&lt;item&gt;<br />
&nbsp; &nbsp; size:12;<br />
&nbsp; &nbsp; number:45;<br />
&nbsp; &nbsp; type:good;<br />
&lt;/item&gt;<br />
END</span><br />
<br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">@result</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$text</span><span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #339933;">!</span><span style="color: #009999;">&lt;item&gt;</span><span style="color: #339933;">.*?&lt;/</span>item<span style="color: #339933;">&gt;!</span>sg<span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">foreach</span> <span style="color: #0000ff;">$item</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">@result</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$item</span> <span style="color: #339933;">!~</span> <span style="color: #009966; font-style: italic;">/color/</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;$item&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>输出结果是:</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;item&gt;<br />
&nbsp; &nbsp; size:12;<br />
&nbsp; &nbsp; number:45;<br />
&nbsp; &nbsp; type:good;<br />
&lt;/item&gt;</div></td></tr></tbody></table></div>
<p>虽然也不错，但是它总是“宁可错杀不可错放”地找完所有可能项，再一一重新进行排除。能否一开始就先界定，我们要找的是<strong>不含color的item</strong>呢？<span style="color:#ff008c">排除型匹配</span>正是为此而生。</p>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">排除型匹配</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<p>不好意思，“排除型匹配”这个词是我生造的。其它的说法或许是“否定断言”，“否定环视”等等。后两者的命名，都是从匹配过程的角度出发；而此处命名，是从结果出发。具体说来，就是使用 <code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!...</span><span style="color: #009900;">&#41;</span></span></code>和<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?&lt;!...</span><span style="color: #009900;">&#41;</span></span></code>作为辅助条件判断，来简化正则表达式，方便快捷地找到符合要求的匹配。</p>
<p>这两个东东的使用方法类似，都是指，当前位置<span style="color:#ff008c">不出现</span>某种模式。不同的是，<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!...</span><span style="color: #009900;">&#41;</span></span></code>是指当前位置的右边，而<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?&lt;!</span><span style="color: #009900;">&#41;</span></span></code>自然就是指左边了。</p>
<p>这里隆重推出<a href="http://anrs.sacredfir.com/" target="_blank" title="我爱正则表达式">Anrs</a>同学翻译的教程: <a href="http://anrs.sacredfir.com/archives/295" target="_blank" title="我爱正则表达式">环视一</a>以及<a href="http://anrs.sacredfir.com/archives/338" target="_blank" title="我爱正则表达式">环视二</a>。仔细阅读这两文章，彻底明白环视这两个概念，将会提升您的正则表达式功力。后文将建立在您已经理解环视这个概念的基础上。</p>
<p>闲话一句。既然使用“左边”和“右边”既形象又好懂，为什么没见过“左瞻”，“右瞻”，“左向”，“右向”，反而全是些“前瞻后瞻”，“正向逆向”这样的不好理解的说法呢？<a href="https://twitter.com/kwl_01_skz/status/14069944812" target="_blank" title="我爱正则表达式">撕烤者</a>也同有此问。我的理解是，或许是为了照顾阿语等从右向左书写的用户的习惯吧。无论如何，将从 <code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">^</span></span></code>到 <code class="codecolorer perl default"><span class="perl">$</span></code>的方向称之为“向前”总不会错。</p>
<p>描述当前位置（左侧或右侧）的模式，从而辅助判断正则式是否匹配，是环视的作用。它只描述，不消耗字符；只辅助判断，从不单独出现。这与<code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">^</span></span></code>和<code class="codecolorer perl default"><span class="perl">$</span></code>简直如出一辙。</p>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">一则例子</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<p><strong>例子. </strong>现在有许多与fanfou.com类似的网址。如何写一条正则表达式，来匹配域名含fanfou，但是TLS不是.com的模式？</p>
<p><strong>答案：</strong><code class="codecolorer perl default"><span class="perl"><span style="color: #339933;">/</span><span style="color: #0000ff;">\bfanfou</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>com<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span>a<span style="color: #339933;">-</span>z<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#125;</span><span style="color: #0000ff;">\b</span><span style="color: #339933;">/</span>i</span></code>。分析这条正则表达式：</p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<ul>
<li>以<code class="codecolorer perl default"><span class="perl"><span style="color: #0000ff;">\b</span></span></code>开始，明确字符边界；</li>
<li>fanfou主域名不可少；</li>
<li><code class="codecolorer perl default"><span class="perl">\<span style="color: #339933;">.</span></span></code>匹配一个普通的点号；此处不要使用点号元字符；</li>
<li><code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>com<span style="color: #009900;">&#41;</span></span></code>表示此处（即从<code class="codecolorer text default"><span class="text">fanfou.</span></code>的右边）不得出现com三个连续字符；</li>
<li><code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#91;</span>a<span style="color: #339933;">-</span>z<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#125;</span></span></code>表示是2至4位的拉丁字母；因为域名的TLS最短是2位（如.au, .us），最长可为4位（如.info, .asia）；</li>
<li>右侧边界同样重要，否则我们之前的{2,4}就白费了；</li>
<li>使用i表示不分大小写；这是域名的特征之一。</li>
</ul>
</blockquote>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">回到本题</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>
        按照要求，一步步建立这条正则式。</p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<ul>
<li>该正则式匹配的是<code class="codecolorer text default"><span class="text">&lt;item&gt;...&lt;/item&gt;</span></code>结构。因此，正则式以<code class="codecolorer perl default"><span class="perl"><span style="color: #009999;">&lt;item&gt;</span></span></code>开始。</li>
<li>在<code class="codecolorer text default"><span class="text">&lt;item&gt;</span></code>和<code class="codecolorer text default"><span class="text">&lt;/item&gt;</span></code>之间不得出现color，是这条正则式的难点。因为，<code class="codecolorer text default"><span class="text">color</span></code>可能位于这个结构之内的任意一点，因此要规定，此内任意一点都不得出现color一词。这样的点为：<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>color<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span></span></code>。这样的点重复1+次，正则式写为<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>color<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span></span></code>。注意这里有个小陷阱：不要写为<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>color<span style="color: #009900;">&#41;</span><span style="color: #339933;">.+</span></span></code>，否则它只描述了最左侧的一点不得出现color，其余部分则都无所谓。而写为<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>color<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span></span></code>则保证每一点都不出现color。</li>
<li>正则式此时为<code class="codecolorer perl default"><span class="perl"><span style="color: #009999;">&lt;item&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>color<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+?&lt;/</span>item<span style="color: #339933;">&gt;</span></span></code>。为了节省资源，括号通常写成非捕获模式<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#40;</span><span style="color: #339933;">?:...</span><span style="color: #009900;">&#41;</span></span></code>；为了保证点号匹配换行符，可以指定s模式或使用<code class="codecolorer perl default"><span class="perl"><span style="color: #009900;">&#91;</span>\<span style="color: #000066;">s</span><span style="color: #0000ff;">\S</span><span style="color: #009900;">&#93;</span></span></code>代替点号元字符。此处仍使用点号。正则式修改为<code class="codecolorer perl default"><span class="perl"><span style="color: #009999;">&lt;item&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?:</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?!</span>color<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+?&lt;/</span>item<span style="color: #339933;">&gt;</span></span></code>。</li>
</ul>
</blockquote>
</blockquote>
</blockquote>
<p>总体来说，环视相对于基本的元字符还是要抽象一些。不过一旦理解并掌握了它，就会发现它在精确匹配和替换时十分有用。上面的分析，希望有所帮助。如果您有类似的问题，欢迎提出。</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/negate-match.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP中的递归正则</title>
		<link>http://iregex.org/blog/recursive-regex-in-php.html</link>
		<comments>http://iregex.org/blog/recursive-regex-in-php.html#comments</comments>
		<pubDate>Mon, 10 May 2010 04:57:28 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[翻译]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[recursive]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=84</guid>
		<description><![CDATA[之前一篇文章翻译了Perl语言中的递归正则表达式. 其实不少语言中的正则都是支持递归的, 例如本文要介绍的PHP正则递归. 虽然, 工作中最常用的正则表达式都很&#8221;正则&#8221;, 只用最基本的语... ]]></description>
			<content:encoded><![CDATA[<p>之前一篇文章翻译了<a title="我爱正则表达式|Perl语言中的递归正则表达式" target="_blank" href="http://iregex.org/blog/recursive-regular-expressions.html">Perl语言中的递归正则表达式</a>. 其实不少语言中的正则都是支持递归的, 例如本文要介绍的PHP正则递归. 虽然, 工作中最常用的正则表达式都很&#8221;正则&#8221;, 只用最基本的语法就能解决85%以上的问题, 而且合理有效地使用普通正则来解决复杂问题也是一门技巧与学问; 但是高级一点的语法的确有它存的价值, 有时不用它还真办不了事儿; 况且学习正则的乐趣也在于<font color="#ff008c">尝试各种各样的可能性, 满足自己无穷无尽的好奇心</font>.</p>
<p><a href="http://iregex.org/blog/recursive-regex-in-php.html" title="我爱正则表达式 | PHP中的递归正则">本文</a>内容, 整理自网文<A HREF="http://www.skdevelopment.com/php-regular-expressions.php">Finer points of PHP regular expressions</A>. 其分析过程剥茧抽丝, 丝丝入扣, 值得一读. 该文系统地列出了PHP中正则表达式常见特性, 我只摘取其中递归部分翻译整理出来. </p>
<p></a><span id="more-84"></span></p>
<h2 style="background-color: rgb(153, 204, 0); line-height: 35px; border: 1px solid rgb(102, 102, 102); color: rgb(0, 0, 0); text-indent: 6px; font-size: 21px;">正文</h2>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">例子</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<p>什么时候会用到递归正则表达式呢? 当然是待匹配的字串中递归地出现某种模式时(貌似废话). 最经典的例子, 就是递归正则处理嵌套括号的问题了. 例子如下.  </p>
<p>假设你的文本中包含了正确配对的嵌套括号. 括号的深度可以是无限层. 你想捕获这样的括号组.</p>
<p>恕我剧透, 标准答案是这样的:</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;some text (a(b(c)d)e) more text&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/\(([^()]+|(?R))*\)/&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$string</span><span style="color: #339933;">,</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;pre&gt;&quot;</span><span style="color: #339933;">;</span> <span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;/pre&gt;&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>
<p>其输出结果是:</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #990000;">Array</span><br />
<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span>d<span style="color: #009900;">&#41;</span>e<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> e &nbsp; &nbsp;<br />
<span style="color: #009900;">&#41;</span></div></td></tr></tbody></table></div>
<p>可见, 我们所需要的文本, 已经捕获到<code class="codecolorer php default"><span class="php"><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span></span></code>中了.</p>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">原理</h3>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<p>现在思考原理.</p>
<p>上面的正则表达式中的关键点是<code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>?R<span style="color: #009900;">&#41;</span></span></code>. <code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>?R<span style="color: #009900;">&#41;</span></span></code>的作用就是递归地替换它所在的整条正则表达式. 在每次迭代时, PHP 语法分析器都会将<code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>?R<span style="color: #009900;">&#41;</span></span></code>替换为&#8221;<code class="codecolorer php default"><span class="php">\<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>^<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+|</span><span style="color: #009900;">&#40;</span>?R<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span>\<span style="color: #009900;">&#41;</span></span></code>&#8220;.</p>
<p>因此, 具体到上述的例子, 其正则表达式等价于:</p>
<p>            <code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;/\(([^()]+|\(([^()]+|\(([^()]+)*\))*\))*\)/&quot;</span></span></code></p>
<p>但是上面的代码只适合深度为3层的括号. 对于未知深度的括号嵌套, 就只好使用这种正则了:</p>
<p>            <code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;/\(([^()]+|(?R))*\)/&quot;</span></span></code> </p>
<p>它不但能够匹配无限深度, 还简化了正则表达式的语法. 功能强大, 语法简洁.</p>
<p>现在来细看一下<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;/\(([^()]+|(?R))*\)/&quot;</span></span></code>是怎样匹配<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;(a(b(c)d)e)&quot;</span></span></code>的:</p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<ol>
<li><code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;(c)&quot;</span></span></code>这部分被正则式 <code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;\(([^()]+)*\)&quot;</span></span></code> 匹配. 请注意, <code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span></span></code> 其实就相当于整个递归的一个缩影, 麻雀虽小五脏俱全, 因此它用到了整个正则表达式.<br />换言之, 下一步中的<code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span></span></code>, 可以使用<code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>?R<span style="color: #009900;">&#41;</span></span></code> 来匹配.</li>
<li><code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span>d<span style="color: #009900;">&#41;</span></span></code>的匹配过程为:
<ol>
<li><code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;\(&quot;</span></span></code>匹配<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;(&quot;</span></span></code>;</li>
<li><code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;[^()]+&quot;</span></span></code>匹配<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;b&quot;</span></span></code>;</li>
<li><code class="codecolorer php default"><span class="php">&nbsp;<span style="color: #009900;">&#40;</span>?R<span style="color: #009900;">&#41;</span></span></code>匹配<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;(c)&quot;</span></span></code>;</li>
<li><code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;[^()]+&quot;</span></span></code>匹配<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;d&quot;</span></span></code>;</li>
<li><code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;\)&quot;</span></span></code>匹配<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">&quot;)&quot;</span></span></code>.</li>
</ol>
</li>
</ol>
<p>根据上面的匹配原理, 不难理解为什么数组的第2个元素<code class="codecolorer php default"><span class="php"><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span></span></code>与<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">'e'</span></span></code>等价. 子串<code class="codecolorer php default"><span class="php"><span style="color: #0000ff;">'e'</span></span></code>是在最后一次匹配迭代中被捕获. 匹配过程中, <font color="#ff008c">只有最后一次的捕获结果才会保存到数组中</font>.</p>
<blockquote  style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>rex注: 关于这个特性, 可以自行尝试一下, 看看使用正则式<code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>a<span style="color: #339933;">-</span>z<span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">9</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span></span></code>来匹配字串<code class="codecolorer php default"><span class="php">abc123xyz890</span></code>, 其捕获结果<code class="codecolorer php default"><span class="php">$<span style="color: #cc66cc;">1</span></span></code>是什么. 注意, 其结果与 Left Longest 原理并不冲突.</p></blockquote>
</blockquote>
<p>         如果我们只需要捕获 <code class="codecolorer php default"><span class="php"><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span></span></code>, 可以这样做:</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;some text (a(b(c)d)e) more text&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/\((?:[^()]+|(?R))*\)/&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$string</span><span style="color: #339933;">,</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;pre&gt;&quot;</span><span style="color: #339933;">;</span> <span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;/pre&gt;&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>
<p>产生的结果相同:</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #990000;">Array</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span>d<span style="color: #009900;">&#41;</span>e<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span></div></td></tr></tbody></table></div>
<p>所做的改动是捕获括号<code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code>改为非捕获捕获括号<code class="codecolorer php default"><span class="php"><span style="color: #009900;">&#40;</span>?<span style="color: #339933;">:</span><span style="color: #009900;">&#41;</span></span></code>了.</p>
<p>还可以进一步完善为:</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;some text (a(b(c)d)e) more text&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/\((?&gt;[^()]+|(?R))*\)/&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$string</span><span style="color: #339933;">,</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;pre&gt;&quot;</span><span style="color: #339933;">;</span> <span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;/pre&gt;&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>
<p>这里我们用到了所谓的一次性模式(rex注: 余晟先生译的《精通正则表达式v3.0》中, 谓之&#8221;固化分组&#8221;. 可参考该书.) PHP手册也推荐只要条件允许, 就尽可能使用这种模式, 以便提升正则表达式的速度.</p>
<p>一次性模式很简单, 这里不再详述. 如果感兴趣, 可以参考PHP 官方手册. 如果您想深入学习PERL兼容式正则表达式, 请参考文末链接.<br />
</blockquote>
</blockquote>
<h2  style="background-color: rgb(153, 204, 0); line-height: 35px; border: 1px solid rgb(102, 102, 102); color: rgb(0, 0, 0); text-indent: 6px; font-size: 21px;">提到的链接</h2>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<ul>
<li>原文: <a href="http://www.skdevelopment.com/php-regular-expressions.php">Finer points of PHP regular expressions</a></li>
<li>Perl兼容正则表达式 <a href="http://www.pcre.org">官网</a> <a href="http://pcre.org/pcre.txt">文档</a></li>
<li><a href="http://us3.php.net/manual/en/reference.pcre.pattern.syntax.php">PHP官网的PCRE正则文档</a></li>
</ul>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/recursive-regex-in-php.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>[链接]使用正则表达式搜索文本文件</title>
		<link>http://iregex.org/blog/search-text-file-with-regex.html</link>
		<comments>http://iregex.org/blog/search-text-file-with-regex.html#comments</comments>
		<pubDate>Sat, 27 Mar 2010 09:15:46 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[url ibm newbie]]></category>

		<guid isPermaLink="false">http://iregex.org/blog/%e9%93%be%e6%8e%a5%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%90%9c%e7%b4%a2%e6%96%87%e6%9c%ac%e6%96%87%e4%bb%b6.html</guid>
		<description><![CDATA[IBM文库发布一篇新文章： 学习 Linux，101: 使用正则表达式搜索文本文件-在大海里捞针 正则表达式新手和老手都可以一读。副标题“在大海里捞针”很有意思... ]]></description>
			<content:encoded><![CDATA[<p>IBM文库发布一篇新文章：</p>
<ul>
<li><a href="http://www.ibm.com/developerworks/cn/linux/l-lpic1-v3-103-7/?ca=drs-tp4608">学习 Linux，101: 使用正则表达式搜索文本文件-在大海里捞针</a></li>
</ul>
<p><a href="http://iregex.org" title="我爱正则表达式">正则表达式</a>新手和老手都可以一读。副标题“在大海里捞针”很有意思。</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/search-text-file-with-regex.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>正则表达式匹配规则</title>
		<link>http://iregex.org/blog/how-regular-expression-matches.html</link>
		<comments>http://iregex.org/blog/how-regular-expression-matches.html#comments</comments>
		<pubDate>Sat, 30 Jan 2010 04:55:21 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=75</guid>
		<description><![CDATA[原文：How will my regular expression match? 作者：hv 译文：正则表达式的匹配过程 译者：rex rex译注：在《Programming Perl》第三版第五章，讲了正则匹配的六条规则，深入，透彻，但是不易理解。可以将... ]]></description>
			<content:encoded><![CDATA[<p>原文：<a href="http://www.perlmonks.org/?node_id=371722" target="_blank">How will my regular expression match?</a><br />
作者：<a href="http://www.perlmonks.org/?node_id=209409" target="_blank">hv</a><br />
译文：<a href="http://iregex.org/blog/How-regular-expression-matches.html" target="_blank">正则表达式的匹配过程</a><br />
译者：<a href="http://iregex.org/" target="_blank">rex</a></p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>rex译注：在《Programming Perl》第三版第五章，讲了正则匹配的六条规则，深入，透彻，但是不易理解。可以将本文当作是该章的简化版。另外，一定的正则式调试经验也有助于理解正则式的匹配过程。可以参考《Programming Perl》第五章“正则表达式编译器”一节，或阅读这篇文章《<a href="http://perl.active-venture.com/pod/perldebguts-debugregexp.html">Debugging Regular Expressions</a>》。建议阅读例程序时，先默想输出结果，然后再上机测试，最后再看本文的答案。
</p></blockquote>
<p><span id="more-75"></span></p>
<p>经常见到关于正则表达式“偏好”的讨论，即，正则表达式引擎“喜欢”更长的、更短的，还是最左端的匹配。</p>
<p>事实非常简单：正则表达式引擎总是返回它所匹配到的第一个结果，如果你理解了正则表达式尝试匹配的顺序，你就再也不会对找到哪一个匹配而困惑了。</p>
<p>下面是一些简单规则（次序无关），阐释正则引擎尝试匹配的顺序。</p>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">1．从最左端的字符开始</h3>
<p>引擎从目标字串的第一个字符开始，对正则模式进行匹配测试。只有当在第一个字符位置测试完整个正则模式且匹配失败时，引擎才会移动到目标字串的下一个字符，重新开始匹配测试。这样依次测试，直到字串的结束位置。</p>
<p>例子：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$match</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;The longest word&quot;</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(\w+)/</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>其输出结果是“<font color="#ffffff">The</font>”（请先自行猜测，再使用鼠标选定，查看结果；下同。），原因是匹配是从字串的最左端开始的。这个单词之后，还有一个更长的单词可以匹配，但是正则引擎却对其视而不见：只要从字串开始处进行匹配且成功，它就返回这个结果，匹配过程就结束了。</p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>Rex:如果正则式是以$结尾的，例如abc$，该正则在试图匹配字串“xyzabc”是否会首先跳到最后一个字符开始比较呢？我的理解是，就常规的正则引擎的正常的匹配过程而言，虽然有$符，但是该$符与普通字符一样，不会特殊处理，整条正则式会在x,y,z处失败3次，然后在a处再开始匹配测试并最终成功。$不会加速匹配过程，只是保证了最终匹配位置。但是不排除具体的正则引擎，会对定位锚点进行优化，从而实现early exit，即只要不符合某一条件，就提前退出，从而减少真正的比较次数，提升效率。看一下abc$ 的perl代码：
<p>
<a href="http://iregex.org/blog/How-regular-expression-matches.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/2010-01-30101022.png" border="0" alt="Photobucket"></a><br />
Perl引擎对该正则式的分析是：精确匹配普通文本abc；之后是行尾结束符；结束。在匹配时，它直接就“猜”到了匹配结果。</p></blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">2. 最左边的备选项优先</h3>
<p>如果正则模式中含备选项，那么首先测试左边的选项。如果最左侧的备选项成功匹配，那么就继续使用剩余的正则表达式剩余的字串进行匹配测试；只有在最左边的备选项不能匹配时才依次尝试下一个备选项。</p>
<p>例子：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$match</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;Mrs Smith&quot;</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/(Mr|Mrs)/</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>其输出结果是“<font color="#ffffff">Mr</font>”，因为最左端的正则备选项匹配成功，在本例中也就意味着整个正则表达式匹配成功。此时第二个备选项就被完全无视了。
<p>
<a href="http://iregex.org/blog/How-regular-expression-matches.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/2010-01-30093501.png" border="0" alt="Photobucket"></a></p>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">3. 贪婪模式</h3>
<p>对于任何常规的量词（即? * + {1,3}），引擎首先会尝试允许范围内最大数量的重复次数（如果实际文本不足，则尽可能多地重复），然后继续使用剩余的正则表达式剩余的字串进行匹配测试。只有当剩余的正则匹配失败时，引擎才不情愿地“吐出”一次重复的文本，尝试进行后续的匹配，直到匹配成功，或到达允许重复的最小次数。<br />
例子：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$match</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;/foo/bar&quot;</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">.*/</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">.*</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>其输出结果是&#8221;<font color="#ffffff">bar</font>&#8220;。匹配过程是：</p>
<p>.*先匹配完整个字串/foo/bar；此时发现.*之后还需要匹配一个/，此时只好回退字串，.*此时是/foo/ba，然后是/foo/b，/foo/，/foo。此时，后续的正则式得到了/，得以继续匹配并最终成功，返回它认为正确的结果。看图：
<p>
<a href="http://iregex.org/blog/How-regular-expression-matches.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100130102752.png" border="0" alt="Photobucket"></a></p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>Rex: 如果我们想把下面的英文字串</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">At this point the remaining pattern matches, so this is the match returned</div></td></tr></tbody></table></div>
<p>提取出最后一个单词和其它部分，应该怎样写正则呢？(.*)(\w+)$吗？这样的话，$2中只有d这个字母。正确的写法包括：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">.*</span><span style="color: #0000ff;">\b</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\w</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span>$ &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># .*先用完整个字符，再一个字符一个字符地回退，直到遇到一个单词边界，然后开始找\w+。</span></div></td></tr></tbody></table></div>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">4. 懒惰模式</h3>
<p>在量词之后加上问号?（即?? *? +? {1,3}?），就由贪婪模式变为懒惰模式，匹配的过程也随之改变：引擎先尝试允许范围内最少次数的重复，随即使用后续的正则对后续的字串作匹配测试。只有当后续的正则匹配失败时，引擎才懒洋洋地再吃进一次重复，再进行后续匹配测试，直到匹配成功，或到达所允许的匹配次数上限。<br />
例子：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$match</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;foo/bar/baz&quot;</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">.*?/</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">.*</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>显而易见，输出结果是<font color="#ffffff">bar/baz</font>。匹配过程中，.*?先匹配空字串&#8221;"，然后是&#8221;f&#8221;，&#8221;fo&#8221;，&#8221;foo&#8221;，此时匹配成功，并返回相应结果。</p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>Rex:继续思考上节的问题，另一种将At this point the remaining pattern matches, so this is the match returned中最后一个单词与其余部分分开的正则式还可以是：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">.*?</span><span style="color: #0000ff;">\w</span><span style="color: #339933;">+</span>$</div></td></tr></tbody></table></div>
</blockquote>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">5. 正则式各部分的匹配次序：从左到右</h3>
<p>上面一些例子中的暗含前提是正则模式之间的匹配次序是从左到右。因此在“贪婪模式”例子中有两个.*，基于本条规则，只有当第一个.*的条件满足之后，它才会考虑后续的正则表达式该如何匹配。</p>
<h3 style="color: #127ADB; font-size:14px; padding-bottom:3px; padding-top:3px; margin:1.5em 0 1em;">6. 嵌套</h3>
<p>其实这只是“从左到右”规则的引申。参见下面的例子：</p>
<div class="codecolorer-container perl mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$outer</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$inner</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;/foo/bar&quot;</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">/</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">.+</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066;">print</span> <span style="color: #0000ff;">$inner</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>其输出结果是“<font color="#ffffff">foo/bar</font>”。正则引擎先遇到外层的量词，意识到该部分正则要尽可能多地重复，然后开始尝试匹配内层的正则。嵌于内层的量词是贪婪的，因此也会尽可能多地重复，它抓到的字串是foo/bar这部分。此时，外层量词没有机会再重复一次匹配了，但是没有关系——整个正则表达式已经成功匹配，因此返回相应结果。</p>
<p>本文概括了绝大部分常规正则表达式的匹配规则。其余不常见的情况，仍需留心（例如锚点，pos()，以及各种各样的零宽断言）。同时，正则表达式优化器有时会让引擎略过某些步骤，但前提条件是目标匹配结果不变。</p>
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>Rex注：将何伟平先生译的《Programming Perl》中的正则匹配规则也抄录在这里。只列提纲，需要详细内容的请自行翻书。</p>
<ul>
<li>规则1：引擎试图尽可能地匹配字符串的左边，这样整个正则表达式按照规则2匹配。<br />
引擎从字符串的第一个字符开始，然后从那里开始尝试匹配整个模式。只有引擎在到达字符串的终点之前先到达模式的终点才是整个模式的匹配。如果匹配，引擎马上退出——它不会继续寻找“更好的”匹配，即便模式可能以几种不同的方式匹配也如此。</li>
<li>规则2：当引擎碰到一个候选集合时（用|符号分隔），不管是在顶层还是在当前“群集”层次中，它都从左向右尝试这些候选项，并且在第一个可以成功完成整个模式匹配的候选项处停止。</li>
<li>规则3：如果根据规则4和5（这样整个正则表达式就可以满足了），某个候选项里顺序列出的每个项都匹配，那么这个候选项就是匹配项。<br />
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>（rex注：列出的每个项，觉得这里说“子项”，层次更清晰。）</p></blockquote>
</li>
<li>规则4：如果一个断言不出猎在当前位置匹配，引擎将回溯到规则3并重新以不同的选择试验高强弱顺序的项。</li>
<li>规则5：一个量化的原子只有在其本身匹配了其量词许可的次数才算匹配。（原子本身是按照规则6匹配的）。</li>
<li>规则6：每个原子都根据它的类型指定的语义来匹配。如果该原子 不匹配（或者它匹配而模式的其余部分不匹配），那么引擎将回溯到规则5,然后尝试该原子 的数量的下一选择。</li>
</ul>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/how-regular-expression-matches.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>笔记：如何写出高效率的正则表达式</title>
		<link>http://iregex.org/blog/regex-optimizing.html</link>
		<comments>http://iregex.org/blog/regex-optimizing.html#comments</comments>
		<pubDate>Mon, 30 Nov 2009 14:53:26 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[optimize]]></category>
		<category><![CDATA[regex]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=71</guid>
		<description><![CDATA[如果纯粹是为了挑战自己的正则水平，用来实现一些特效（例如使用正则表达式计算质数、解线性方程），效率不是问题；如果所写的正则表达式只是为了满足一两次、几十次的运行，优化与... ]]></description>
			<content:encoded><![CDATA[<p>如果纯粹是为了挑战自己的正则水平，用来实现一些特效（例如使用正则表达式计算质数、解线性方程），效率不是问题；如果所写的正则表达式只是为了满足一两次、几十次的运行，优化与否区别也不太大。但是，如果所写的正则表达式会百万次、千万次地运行，效率就是很大的问题了。我这里总结了几条提升正则表达式运行效率的经验（工作中学到的，看书学来的，自己的体会），贴在这里。如果您有其它的经验而这里没有提及，欢迎赐教。</p>
<p>为行文方便，先定义两个概念。</p>
<ul>
<li><b>误匹配</b>：指正则表达式所匹配的内容范围超出了所需要范围，有些文本明明不符合要求，但是被所写的正则式“击中了”。例如，如果使用<font color="#3366ff">\d{11}</font>来匹配11位的手机号，<font color="#3366ff">\d{11}</font>不单能匹配正确的手机号，它还会匹配<font color="#cc33cc">98765432100</font>这样的明显不是手机号的字符串。我们把这样的匹配称之为误匹配。</li>
<li><b>漏匹配</b>：指正则表达式所匹配的内容所规定的范围太狭窄，有些文本确实是所需要的，但是所写的正则没有将这种情况囊括在内。例如，使用<font color="#3366ff">\d{18}</font>来匹配18位的身份证号码，就会漏掉结尾是字母X的情况。
</li>
</ul>
<p>写出一条正则表达式，既可能<b>只出现</b>误匹配（条件写得极宽松，其范围大于目标文本），也可能<b>只出现</b>漏匹配（只描述了目标文本中多种情况种的一种），还可能<b>既有误匹配又有漏匹配</b>。例如，使用<font color="#3366ff">\w+\.com</font>来匹配.com结尾的域名，既会误匹配<font color="#cc33cc">abc_.com</font>这样的字串（合法的域名中不含下划线，<font color="#3366ff">\w</font>包含了下划线这种情况），又会漏掉<font color="#cc33cc">ab-c.com</font>这样的域名（合法域名中可以含中划线，但是<font color="#3366ff">\w</font>不匹配中划线）。</p>
<p>精准的正则表达式意味着既无误匹配且无漏匹配。当然，现实中存在这样的情况：只能看到有限数量的文本，根据这些文本写规则，但是这些规则将会用到海量的文本中。这种情况下，尽可能地（如果不是完全地）消除误匹配以及漏匹配，并提升运行效率，就是我们的目标。本文所提出的经验，主要是针对这种情况。</p>
<ol>
<li><b>掌握语法细节</b>。正则表达式在各种语言中，其语法大致相同，细节各有千秋。明确所使用语言的正则的语法的细节，是写出正确、高效正则表达式的基础。例如，perl中与<font color="#3366ff">\w</font>等效的匹配范围是<font color="#3366ff">[a-zA-Z0-9_]</font>；perl正则式不支持肯定逆序环视中使用可变的重复（variable repetition inside lookbehind，例如<font color="#3366ff">(?&lt;=.*)abc</font>），但是.Net语法是支持这一特性的；又如，JavaScript连逆序环视（Lookbehind,如<font color="#3366ff">(?&lt;=ab)c</font>）都不支持，而perl和python是支持的。《精通正则表达式》第3章《正则表达式的特性和流派概览》明确地列出了各大派系正则的异同，<a target="_blank" href="http://iregex.org/blog/regex-syntax-comparison.html">这篇文章</a>也简要地列出了几种常用语言、工具中正则的比较。对于具体使用者而言，至少应该详细了解正在使用的那种工作语言里正则的语法细节。</li>
<li><b>先粗后精，</b><b>先加后减</b>。使用正则表达式语法对于目标文本进行描述和界定，可以像画素描一样，先大致勾勒出框架，再逐步在局步实现细节。仍举刚才的手机号的例子，先界定<font color="#3366ff">\d{11}</font>，总不会错；再细化为<font color="#3366ff">1[358]\d{9}</font>，就向前迈了一大步（至于第二位是不是3、5、8，这里无意深究，只举这样一个例子，说明逐步细化的过程）。这样做的目的是先消除漏匹配（刚开始先尽可能多地匹配，做加法），然后再一点一点地消除误匹配（做减法）。这样有先有后，在考虑时才不易出错，从而向“不误不漏”这个目标迈进。</li>
<li><b>留有余地</b>。所能看到的文本sample是有限的，而待匹配检验的文本是海量的，暂时不可见的。对于这样的情况，在写正则表达式时要跳出所能见到的文本的圈子，开拓思路，作出“战略性前瞻”。例如，经常收到这样的垃圾短信：“发*票”、“发#漂”。如果要写规则屏蔽这样烦人的垃圾短信，不但要能写出可以匹配当前文本的正则表达式 <font color="#3366ff">发[*#](?:票|漂)</font>，还要能够想到 <font color="#3366ff">发.(?:票|漂|飘)</font>之类可能出现的“变种”。这在具体的领域或许会有针对性的规则，不多言。这样做的目的是消除漏匹配，延长正则表达式的生命周期。
</li>
<li><b>明确</b>。具体说来，就是<b>谨慎</b>用点号这样的元字符，<b>尽可能</b>不用星号和加号这样的任意量词。只要能确定范围的，例如\w，就不要用点号；只要能够预测重复次数的，就不要用任意量词。例如，写析取twitter消息的脚本，假设一条消息的xml正文部分结构是&lt;span class=&#8221;msg&#8221;&gt;&#8230;&lt;/span&gt;且正文中无尖括号，那么<font color="#3366ff">&lt;span class=&#8221;msg&#8221;&gt;[^&lt;]{1,480}&lt;/span&gt;</font>这种写法<b>的思路</b>要好于<font color="#3366ff">&lt;span class=&#8221;msg&#8221;&gt;.*&lt;/span&gt;</font>，原因有二：一是使用<font color="#3366ff">[^&lt;]</font>，它保证了文本的范围不会超出下一个小于号所在的位置；二是明确长度范围，<font color="#3366ff">{1,480}</font>，其依据是一条twitter消息大致能的字符长度范围。当然，480这个长度是否正确还可推敲，但是这种思路是值得借鉴的。说得狠一点，“滥用点号、星号和加号是不环保、不负责任的做法”。</li>
<li><b>不要让稻草压死骆驼</b>。每使用一个普通括号()而不是非捕获型括号<font color="#3366ff">(?:&#8230;)</font>，就会保留一部分内存等着你再次访问。这样的正则表达式、无限次地运行次数，无异于一根根稻草的堆加，终于能将骆驼压死。养成合理使用(?:&#8230;)括号的习惯。</li>
<li><b>宁简勿繁</b>。将一条复杂的正则表达式拆分为两条或多条简单的正则表达式，编程难度会降低，运行效率会提升。例如用来消除行首和行尾空白字符的正则表达式<font color="#3366ff">s/^\s+|\s+$//g;</font>，其运行效率理论上要低于<font color="#3366ff">s/^\s+//g; s/\s+$//g;</font> 。这个例子出自《精通正则表达式》第五章，书中对它的评论是“它几乎总是最快的，而且显然最容易理解”。既快又容易理解，何乐而不为？工作中我们还有其它的理由要将C==<font color="#3366ff">(A|B)</font>这样的正则表达式拆为A和B两条表达式分别执行。例如，虽然A和B这两种情况只要有一种能够击中所需要的文本模式就会成功匹配，但是如果只要有一条子表达式（例如A）会产生误匹配，那么不论其它的子表达式（例如B）效率如何之高，范围如何精准，C的总体精准度也会因A而受到影响。</li>
<li><b>巧妙定位</b>。有时候，我们需要匹配的the，是作为单词的the（两边有空格），而不是作为单词一部分的t-h-e的有序排列（例如toge<font color="#cc33cc">the</font>r中的the）。在适当的时候用上<font color="#3366ff">^</font>，<font color="#3366ff">$</font>，<font color="#3366ff">\b</font>等等定位锚点，能有效提升找到成功匹配、淘汰不成功匹配的效率。
</li>
</ol>
<p>总结完发现，《精通正则表达式》的第5章、第6章已经以更为有条理的方式总结出了常用的优化方法。不过，泛泛地读过的印象是肤浅的，过后即忘的；而真正若有所悟时在书上得到了系统地印证，这种感觉才是真的爽。</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/regex-optimizing.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>[转]理解正则表达式</title>
		<link>http://iregex.org/blog/to-understand-regular-expressions.html</link>
		<comments>http://iregex.org/blog/to-understand-regular-expressions.html#comments</comments>
		<pubDate>Sun, 30 Aug 2009 13:34:18 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[DFA]]></category>
		<category><![CDATA[NFA]]></category>
		<category><![CDATA[编译原理]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=64</guid>
		<description><![CDATA[rex注：本文原作者孟岩，原文转自孟岩CSDN博客。本文为《程序员》07年3月号《七种武器》专题所做。rex以前只是知道如何使用正则表达式而已，在读MRE时，读到NFA、DFA其实都是一头雾水，不知... ]]></description>
			<content:encoded><![CDATA[<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;"><p>rex注：本文原作者孟岩，原文转自<a href="http://blog.csdn.net/myan/archive/2007/03/03/1520033.aspx" target="_blank">孟岩CSDN博客</a>。本文为《程序员》07年3月号《七种武器》专题所做。rex以前只是知道如何使用正则表达式而已，在读MRE时，读到NFA、DFA其实都是一头雾水，不知所云。现在抓紧时间恶补基础知识，学习了些编译原理，这才有些明白。如今再看从源头讲正则表达式的文章，就心有戚戚了，呵呵。搜到好文章一篇，与大家分享。
</p></blockquote>
<p>在程序员日常工作中，数据处理占据了相当的比重。而在所有的数据之中，文本又占据了相当的比重。文本能够被人理解，具有良好的透明性，利于系统的开发、测试和维护。然而，易于被人理解的文本数据，机器处理起来就不一定都那么容易。文本数据复杂多变，特定性强，甚至是千奇百怪。因此，文本处理程序可谓生存环境恶劣。一般来说，文本处理程序都是特定于应用的，一个项目有一个项目的要求，彼此之间很难抽出共同点，代码很难复用，往往是&#8220;一次编码，一次运行，到处补丁&#8221;。其程序结构散乱丑陋，谈不上有什么&#8220;艺术性&#8221;，基本上与&#8220;模式&#8221;、&#8220;架构&#8221;什么的无缘。在这里，从容雅致、温文尔雅派不上用场，要想生存就必须以暴制暴。<br />事实上，几十年的实践证明，除了正则表达式和更高级的parser技术，在这样一场街头斗殴中别无利器。而其中，尤以正则表达式最为常用。所以，对于今天的程序员来说，熟练使用正则表达式着实应该是一种必不可少的基本功。然而现实情况却是，知道的人很多，善于应用的人却很少，而能够洞悉其原理，理智而高效地应用它的人则少之又少。大多数开发者被它的外表吓倒，不敢也不耐烦深入了解其原理。事实上，正则表达式背后的原理并不复杂，只要耐心学习，积极实践，理解正则表达式并不困难。下面列举的一些条款，来自我本人学习和时间经验的不完全总结。由于水平和篇幅所限，只能浮光掠影，不足和谬误之处，希望得到有识之士的指教。</p>
<p>1.&nbsp;了解正则表达式的历史<br />正则表达式萌芽于1940年代的神经生理学研究，由著名数学家Stephen Kleene第一个正式描述。具体地说，Kleene归纳了前述的神经生理学研究，在一篇题为《正则集代数》的论文中定义了&#8220;正则集&#8221;，并在其上定义了一个代数系统，并且引入了一种记号系统来描述正则集，这种记号系统被他称为&#8220;正则表达式&#8221;。在理论数学的圈子里被研究了几十年之后，1968年，后来发明了UNIX系统的Ken Thompson第一个把正则表达式用于计算机领域，开发了qed和grep两个实用文本处理工具，取得了巨大成功。在此后十几年里，一大批一流计算机科学家和黑客对正则表达式进行了密集的研究和实践。在1980年代早期，UNIX运动的两个中心贝尔实验室和加州大学伯克利分校分别围绕grep工具对正则表达式引擎进行了研究和实现。与之同时，编译器&#8220;龙书&#8221;的作者Alfred Aho开发了Egrep工具，大大扩展和增强了正则表达式的功能。此后，他又与《C程序设计语言》的作者Brian Kernighan等三人一起发明了流行的awk文本编辑语言。到了1986年，正则表达式迎来了一次飞跃。先是C语言顶级黑客Henry Spencer以源代码形式发布了一个用C语言写成的正则表达式程序库（当时还不叫open source），从而把正则表达式的奥妙带入寻常百姓家，然后是技术怪杰Larry Wall横空出世，发布了Perl语言的第一个版本。自那以后，Perl一直是正则表达式的旗手，可以说，今天正则表达式的标准和地位是由Perl塑造的。Perl 5.x发布以后，正则表达式进入了稳定成熟期，其强大能力已经征服了几乎所有主流语言平台，成为每个专业开发者都必须掌握的基本工具。</p>
<p>2.&nbsp;掌握一门正则表达式语言<br />使用正则表达式有两种方法，一种是通过程序库，另一种是通过内置了正则表达式引擎的语言本身。前者的代表是Java、.NET、C/C++、Python，后者的代表则是Perl、Ruby、JavaScript和一些新兴语言，如Groovy等。如果学习正则表达式的目标仅仅是应付日常应用，则通过程序库使用就可以。但只有掌握一门正则表达式语言，才能够将正则表达式变成编程的直觉本能，达到较高的水准。不但如此，正则表达式语言也能够在实践中提供更高的开发和执行效率。因此，有心者应当掌握一门正则表达式语言。</p>
<p>3.&nbsp;理解DFA和NFA<br />正则表达式引擎分成两类，一类称为DFA（确定性有穷自动机），另一类称为NFA（非确定性有穷自动机）。两类引擎要顺利工作，都必须有一个正则式和一个文本串，一个捏在手里，一个吃下去。DFA捏着文本串去比较正则式，看到一个子正则式，就把可能的匹配串全标注出来，然后再看正则式的下一个部分，根据新的匹配结果更新标注。而NFA是捏着正则式去比文本，吃掉一个字符，就把它跟正则式比较，匹配就记下来：&#8220;某年某月某日在某处匹配上了！&#8221;，然后接着往下干。一旦不匹配，就把刚吃的这个字符吐出来，一个个的吐，直到回到上一次匹配的地方。<br />DFA与NFA机制上的不同带来5个影响：<br />1.&nbsp;DFA对于文本串里的每一个字符只需扫描一次，比较快，但特性较少；NFA要翻来覆去吃字符、吐字符，速度慢，但是特性丰富，所以反而应用广泛，当今主要的正则表达式引擎，如Perl、Ruby、Python的re模块、Java和.NET的regex库，都是NFA的。<br />2.&nbsp;只有NFA才支持lazy和backreference等特性；<br />3.&nbsp;NFA急于邀功请赏，所以最左子正则式优先匹配成功，因此偶尔会错过最佳匹配结果；DFA则是&#8220;最长的左子正则式优先匹配成功&#8221;。<br />4.&nbsp;NFA缺省采用greedy量词（见item 4）；<br />5.&nbsp;NFA可能会陷入递归调用的陷阱而表现得性能极差。</p>
<p>我这里举一个例子来说明第3个影响。</p>
<p>例如用正则式/perl|perlman/来匹配文本 &#8216;perlman book&#8217;。如果是NFA，则以正则式为导向，手里捏着正则式，眼睛看着文本，一个字符一个字符的吃，吃完 &#8216;perl&#8217; 以后，跟第一个子正则式/perl/已经匹配上了，于是记录在案，往下再看，吃进一个 &#8216;m&#8217;，这下糟了，跟子式/perl/不匹配了，于是把m吐出来，向上汇报说成功匹配 &#8216;perl&#8217;，不再关心其他，也不尝试后面那个子正则式/perlman/，自然也就看不到那个更好的答案了。</p>
<p>如果是DFA，它是以文本为导向，手里捏着文本，眼睛看着正则式，一口一口的吃。吃到/p/，就在手里的 &#8216;p&#8217; 上打一个钩，记上一笔，说这个字符已经匹配上了，然后往下吃。当看到 /perl/ 之后，DFA不会停，会尝试再吃一口。这时候，第一个子正则式已经山穷水尽了，没得吃了，于是就甩掉它，去吃第二个子正则式的/m/。这一吃好了，因为又匹配上了，于是接着往下吃。直到把正则式吃完，心满意足往上报告说成功匹配了 &#8216;perlman&#8217;。</p>
<p>由此可知，要让NFA正确工作，应该使用 /perlman|perl/ 模式。</p>
<p>通过以上例子，可以理解为什么NFA是最左子式匹配，而DFA是最长左子式匹配。实际上，如果仔细分析，关于NFA和DFA的不同之处，都可以找出道理。而明白这些道理，对于有效应用正则表达式是非常有意义的。<br />4.&nbsp;理解greedy和lazy量词<br />由于日常遇到的正则表达式引擎全都是NFA，所以缺省都采用greedy量词。Greedy量词的意思不难理解，就是对于/.*/、/\w+/这样的&#8220;重复n&#8221;次的模式，以贪婪方式进行，尽可能匹配更多字符，直到不得以罢手为止。</p>
<p>举一个例子，以 /&lt;.*&gt;/ 模式匹配 &#8216;&lt;book&gt; &lt;title&gt; Perl Hacks &lt;/title&gt; &lt;/book&gt;\t&#8217;文本，匹配结果不是 &#8216;&lt;book&gt;&#8217;，而是 &#8216;&lt;book&gt; &lt;title&gt; Perl Hacks &lt;/title&gt; &lt;/book&gt;&#8217;。原因就在于NFA引擎以贪婪方式执行&#8220;重复n次&#8221;的命令。让我们来仔细分析一下这个过程。</p>
<p>条款3指出，NFA的模型是以正则式为导向，拿着正则式吃文本。在上面的例子里，当它拿着/.*/这个正则式去吃文本的时候，缺省情况下它就这么一路吃下去，即使碰到 &#8216;&gt;&#8217;字符也不罢手——既然 /./ 是匹配任意字符， &#8216;&gt;&#8217; 当然也可以匹配！所以就尽管吃下去，直到吃完遇到结尾（包括\t字符）也不觉得有什么不对。这个时候它突然发现，在正则表达式最后还有一个 /&gt;/，于是慌了神，知道吃多了，于是就开始一个字符一个字符的往回吐，直到吐出倒数第二个字符 &#8216;&gt;&#8217;，完成了与正则式的匹配，才长舒一口气，向上汇报，匹配字符串从第一个字符 &#8216;&lt;&#8217; 开始，到倒数第二个字符 &#8216;&gt;&#8217;结束，即&#8217;&lt;book&gt; &lt;title&gt; Perl Hacks &lt;/title&gt; &lt;/book&gt;&#8217;。</p>
<p>Greedy量词的行为有时确实是用户所需要的，有时则不是。比如在这个例子里，用户可能实际上想得到的是 &#8216;book&#8217; 串。怎么办呢？这时候lazy量词就派上用场了。把模式改为/&lt;.*?&gt;/就可以得到 &#8216;book&#8217;。这个加在 &#8216;*&#8217;号后面的 &#8216;?&#8217; 把greedy量词行为变成lazy量词行为，从而由尽量多吃变为尽量少吃，只要吃到一个 &#8216;&gt;&#8217;立刻停止。</p>
<p>问号在正则表达式里用途最广泛，这里是很重要的一个用途。</p>
<p>5.&nbsp;理解backtracking<br />在条款4的基础上解释backtracking就很容易了。当NFA发现自己吃多了，一个一个往回吐，边吐边找匹配，这个过程叫做backtracking。由于存在这个过程，在NFA匹配过程中，特别是在编写不合理的正则式匹配过程中，文本被反复扫描，效率损失是不小的。明白这个道理，对于写出高效的正则表达式很有帮助。<br />&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/to-understand-regular-expressions.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wordpress UTF8 中文字数统计插件</title>
		<link>http://iregex.org/blog/wordpress-word-counter-for-utf8-chinese.html</link>
		<comments>http://iregex.org/blog/wordpress-word-counter-for-utf8-chinese.html#comments</comments>
		<pubDate>Fri, 02 Jan 2009 14:37:55 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[chinese]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[utf8]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=50</guid>
		<description><![CDATA[最近想在博客中实现这样的功能：“本文字数XXX，继续阅读&#8230;”。在网上找了一款Word Count Plugin for WordPress，作者是 Murray Williams，可惜它只能统计英文单词数，却不能统计中文字数。我下载... ]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://iregex.org/blog/wordpress-word-counter-for-utf8-chinese.html"><img src="http://i293.photobucket.com/albums/mm60/zhasm/wordpressutf8-1.png" /></a> </p>
<p>最近想在博客中实现这样的功能：“本文字数XXX，继续阅读&#8230;”。在网上找了一款<a target="_blank" href="http://www.murraywilliams.com/software/word-count-plugin-for-wordpress/" rel="nofollow">Word Count Plugin for WordPress</a>，作者是 <a target="_blank" href="http://www.murraywilliams.com/">Murray Williams</a>，可惜它只能统计英文单词数，却不能统计中文字数。我下载了源码，自己动手修改，实现了想要的功能。修改过程中涉及了PHP语言中如何使用<a target="_blank" href="http://iregex.org">正则表达式</a>来匹配中文，于是我把过程写这在里。 </p>
<p><span id="more-50"></span><br />
该插件的核心部分是这样的：</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> mtw_wordcount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$page</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pages</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #990000;">function_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'str_word_count'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">str_word_count</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$page</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">,</span><span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$page</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>看来，它并没有自己来数字数，还是调用PHP函数str_word_count实现的。查文档，找到它的官方文档，<a title="http://us2.php.net/str_word_count" href="http://us2.php.net/str_word_count">http://us2.php.net/str_word_count</a>。它能统计字串中的英文单词数，按要求返回单词数目或单方数组。其原理是以默认或指定的分隔符来将字串分隔，再逐个统计。由于该函数对utf8无效，应该使用utf8版：<a target="_blank" href="http://us2.php.net/manual/en/function.str-word-count.php#85592">str_word_count_utf8</a>。</p>
<p>英文的单词之间有空格等分隔符，中文的应该怎样统计呢？由于WordPress的中文字符编码为utf8，我们就从utf8入手。根据以前我写过一篇文章《<a target="_blank" href="http://iregex.org/blog/regex-to-match-chinese.html">匹配中文的正则表达式</a>》可知，在utf8中，匹配单个汉字的正则式是[\x80-\xff]{3}。这样一来，只要将中文的每一个单字视为一个英语单词来处理，那么统计出来的单词数量就应该是正确的。例如，</p>
<p><tt class="string">你好，世界。Hello world.</tt></p>
<p>我的处理方法是，将所有的中文单字替换成两边带空格的英文字母a，即使用正则表达式：</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/[\x80-\xff]{3}/'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">' a '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>考虑到中文标点不计入总数，前边还应该有一条：</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> &nbsp;<span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/～|！|｀|·|＃|￥|％|…|—|<br />
（|）|＋|－|＝|｛|｝|［|］|\＼|｜|“|”|’|‘|；|：|《|》|〈|〉|、|？|。|，/&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">,</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>此时运行程序，得到正确的结果：6。</p>
<p>wordpress UTF8 中文字数统计插件完整的PHP程序是：</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
load_plugin_textdomain<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mtw-wordcount'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'wp-content/plugins/mtw-wordcount'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">/*&nbsp; Call this from inside &quot;The Loop&quot; (see WordPress documentation) to get<br />
&nbsp; &nbsp; a WordCount of the current posting. Function RETURNS the Word Count as<br />
&nbsp; &nbsp; a value, it does not automatically display (ie. 'echo') the value.<br />
&nbsp;*/</span><br />
<br />
&nbsp; &nbsp; <span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;WORD_COUNT_MASK&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;/\p{L}[\p{L}\p{Mn}\p{Pd}'\x{2019}]*/u&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">function</span> str_word_count_utf8<span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #339933;">,</span> <span style="color: #000088;">$format</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> &nbsp;<span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/～|！|｀|·|＃|￥|％|…|—|（|）|＋|－|＝|｛|｝|［|］|\＼|｜|“|”|’|‘|；|：|《|》|〈|〉|、|？|。|，/&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">,</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/[\x80-\xff]{3}/'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">' a '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">switch</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$format</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span>WORD_COUNT_MASK<span style="color: #339933;">,</span> <span style="color: #000088;">$string</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span>WORD_COUNT_MASK<span style="color: #339933;">,</span> <span style="color: #000088;">$string</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #339933;">,</span> PREG_OFFSET_CAPTURE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$result</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span>WORD_COUNT_MASK<span style="color: #339933;">,</span> <span style="color: #000088;">$string</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> mtw_wordcount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$page</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pages</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">function_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'str_word_count_utf8'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> str_word_count_utf8<span style="color: #009900;">&#40;</span><span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$page</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">,</span><span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$page</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">/*&nbsp; Auxilliary method. In case you want to use this somewhere outside the<br />
&nbsp; &nbsp; loop, where the $page and $pages globals don't necessarily work. Pass<br />
&nbsp; &nbsp; the string you want counted instead.<br />
*/</span><br />
<span style="color: #000000; font-weight: bold;">function</span> mtw_string_wordcount<span style="color: #009900;">&#40;</span><span style="color: #000088;">$instring</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">function_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'str_word_count_utf8'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> str_word_count_utf8<span style="color: #009900;">&#40;</span><span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$instring</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">,</span><span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$instring</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>
<p>这样修改后，该插件就能在wp中正确统计中文字数。我的使用方法是：</p>
<div class="codecolorer-container php mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> the_content<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;本文共计&quot;</span><span style="color: #339933;">.</span>mtw_wordcount<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'字，已浏览'</span><span style="color: #339933;">.</span>the_views<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'次。　继续阅读... »'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>
<p>其中的the_views(&quot;&quot;,false)部分是另一款插件<a href="http://fantasyworld.idv.tw/programs/wp_postviews_plus/">WP-PostViews Plus</a>实现的效果，不赘述。</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/wordpress-word-counter-for-utf8-chinese.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>在Excel VBA中使用正则表达式</title>
		<link>http://iregex.org/blog/regex-in-excel-vba.html</link>
		<comments>http://iregex.org/blog/regex-in-excel-vba.html#comments</comments>
		<pubDate>Thu, 25 Dec 2008 03:24:32 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[教程]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[languages]]></category>
		<category><![CDATA[vba]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=43</guid>
		<description><![CDATA[在Excel中使用正则式，需要借助于Excel自带的Visual Basic环境。我查了一下Microsoft Office Excel 2007 Formulas &#38; Functions FOR DUMmIES以及Excel VBA Programming For Dummies，两本书中均没有关于正则表达式的函数，... ]]></description>
			<content:encoded><![CDATA[<p><a title="在Excel中使用正则表达式|题图|我爱正则表达式" target="_blank" href="http://iregex.org/blog/regex-in-excel-vba.html"><img border="0" alt="在Excel中使用正则表达式|题图|我爱正则表达式" src="http://i293.photobucket.com/albums/mm60/zhasm/regex_in_excel.png" /></a></p>
<p>在Excel中使用<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则式</a>，需要借助于Excel自带的Visual Basic环境。我查了一下Microsoft Office Excel 2007 Formulas &amp; Functions FOR DUMmIES以及Excel VBA Programming For Dummies，两本书中均没有关于<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则表达式</a>的函数，也没有关于如何在VB中使用<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则表达式</a>的介绍。不过，我还是在google中使用excel 和regex 作为关键词找到了答案，总结在这里。我没怎么使用过VB，这里的代码只是浅尝辄止式，能够运行而已。本文假设读者有实际操作Excel VBA的经验。</p>
<p><span id="more-43"></span></p>
<p><strong>1. 创建按钮</strong></p>
<p>在Excel中可以方便地加入按钮，方法是右键点击菜单栏空白处，选中Visual Basic选项，在弹出的VB工具栏中点击<strong>控件工具箱</strong>，然后点击其中的“命令按钮”，再在当前工作表中合适位置拖动，即可创建一个按钮。如图所示。</p>
<ul>
<li><a title="我爱正则表达式|http://iregex.org" target="_blank" href="http://iregex.org/blog/regex-in-excel-vba.html"><img border="0" alt="我爱正则表达式|http://iregex.org" src="http://i293.photobucket.com/albums/mm60/zhasm/vb_menu.png" /></a> </li>
<li><a title="我爱正则表达式|http://iregex.org" target="_blank" href="http://iregex.org/blog/regex-in-excel-vba.html"><img border="0" alt="我爱正则表达式|http://iregex.org" src="http://i293.photobucket.com/albums/mm60/zhasm/vb_control.png" /></a> </li>
<li><a title="我爱正则表达式|http://iregex.org" target="_blank" href="http://iregex.org/blog/regex-in-excel-vba.html"><img border="0" alt="我爱正则表达式|http://iregex.org" src="http://i293.photobucket.com/albums/mm60/zhasm/vb_excel.png" /></a> </li>
</ul>
<p><strong>2. 代码框架：将该按钮与VB代码相关联。</strong></p>
<p>在菜单-&gt;宏-&gt;Visual Basic 编辑器中，为CommandButton1_Click()添加代码如下：</p>
<div class="codecolorer-container vb mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Private</span> <span style="color: #000080;">Sub</span> CommandButton1_Click()<br />
<span style="color: #000080;">Dim</span> RegEx &nbsp; &nbsp; &nbsp;<span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #000080;">Dim</span> Myrange <span style="color: #000080;">As</span> Range, C <span style="color: #000080;">As</span> Range<br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' 将RegEx设置为vbscript.regexp正则对象<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">Set</span> RegEx = CreateObject(<span style="color: #800000;">&quot;vbscript.regexp&quot;</span>)<br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' 设置RegExp 的属性<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">With</span> RegEx<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'look for global matches 全局匹配<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;.Global = <span style="color: #000080;">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' 选择非数字的文本<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;.Pattern = <span style="color: #800000;">&quot;[^\d]+&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' 将当前活动工作表中的所有批注赋值给cmt<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">Set</span> cmt = ActiveSheet.Comments<br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> xC <span style="color: #000080;">In</span> cmt<br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">'对于每一条批注,删除其中的非数字文本,只留下数字文本<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;xC.Text RegEx.Replace(xC.Text, <span style="color: #800000;">&quot;&quot;</span>)<br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> Myrange = <span style="color: #000080;">Nothing</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> RegEx = <span style="color: #000080;">Nothing</span><br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></td></tr></tbody></table></div>
<p>上面代码的作用是将当前活动工作表中所有的批注中的非数字内容删除。例如，如果某单元格的批注为“ab1234cd” ，则执行代码后，其结果是“1234”。</p>
<p>回到工作表中，新建几条同时含数字和非数字内容的批注，执行代码，则其中的非数字项会被删除。</p>
<p><strong>3. 分析代码</strong></p>
<p>步骤2展示的是如何在Excel中调用<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则表达式</a>来处理文本。总结一下，其过程如下：</p>
<ol>
<li>声明<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则式</a>对象； </li>
<li>赋值给该对象，包括全局性、大小写模式、<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则式</a>内容； </li>
<li>执行<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则表达式</a>。 </li>
</ol>
<p>执行<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则表达式</a>时，我们有3种函数可用：Test、Execute、Replace。</p>
<ul>
<li>Test：检测目标文本与<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则式</a>是否匹配，返回True or False。 </li>
<li>Execute：检测是否匹配，并返回匹配集合，供后续程序调用处理。 </li>
<li>Replace：执行替换操作。在替换时，可以使用$1,$2等捕获变量，与常规的<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则表达式</a>意义相同，不赘述。 </li>
</ul>
<p><strong>4. 应用举例</strong></p>
<p>单纯的<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则式</a>应用很简单，难点在于在不同的场合和环境中，结合目标语言，正确使用它。在Excel中使用<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则式</a>，我认为应该特别注意的地方是Excel的独特的变量、活动表格、单元格范围，诸如此类。不过，这些内容应该可以通过查询帮助文档来获得。文末附了几本与Excel、VB编程相关的书籍，可供参考。</p>
<p>这里再举一则Execute函数的例子。</p>
<div class="codecolorer-container vb mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Private</span> <span style="color: #000080;">Sub</span> CommandButton2_Click()<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Dim</span> myRegExp <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Dim</span> Myrange <span style="color: #000080;">As</span> Range, C <span style="color: #000080;">As</span> Range<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> myRegExp = CreateObject(<span style="color: #800000;">&quot;vbscript.regexp&quot;</span>)<br />
&nbsp; &nbsp; myRegExp.Pattern = <span style="color: #800000;">&quot;(\d{4})(\w{2})&quot;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> Myrange = ActiveSheet.Range(<span style="color: #800000;">&quot;B3:B7&quot;</span>)<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> C <span style="color: #000080;">In</span> Myrange<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">Set</span> myMatches = myRegExp.Execute(C.Value)<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">If</span> myMatches.Count &gt;= 1 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">Set</span> myMatch = myMatches(0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">If</span> myMatch.SubMatches.Count &gt;= 2 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MsgBox myMatch.SubMatches(0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'第一组匹配，(\d{4})部分<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox myMatch.SubMatches(1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'第二组匹配，(\w{2})部分<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span><br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></td></tr></tbody></table></div>
<p>本程序的作用是将当前活动工作表中B3:B12范围单元格内的连续4位的数字取出来，使用MsgBox形式输出。执行结果为：</p>
<ol>
<li>B3单元格匹配，结果为2323、ac。 </li>
<li>B7单元格匹配，结果为3233、23。 </li>
</ol>
<p>文中的程序在MS Office 2003 Excel下通过。</p>
<p>附：与Excel、VBA、<a title="http://iregex.org|我爱正则表达式" target="_blank" href="http://iregex.org">正则表达式</a>相关的一些资源：</p>
<ul>
<li><a title="我爱正则表达式" target="_blank" href="http://qlh1bw.bay.livefilestore.com/y1pB0vUggWmzwXjN7Ve1mJKRY4H3fyAVbd2TuqBaMIzne-I_TE5YyIMsPXQVAfLCvC4kB_Aotuq1nL-_1UteoZvWw/RegExp%20Sept%201%202004.7z?download">RegExp Sept 1 2004.xls</a><sup><font color="#ff0080">荐！</font></sup>，一个200k的excel文档（英文），Excel下正则式运用之典范。运行时请将<font color="#ff00ff">工具-&gt;宏-&gt;安全性</font>调至<font color="#ff00ff">低</font>。 </li>
<li><a target="_blank" href="http://rapidshare.com/files/158521742/0470046554.zip">Excel 2007 Formulas &amp; Functions FOR DUMmIES</a> （386页英文PDF，9.16Mb，需登录该页面下载，下同。） </li>
<li><a target="_blank" href="http://rapidshare.com/files/154427001/0764574124.pdf">Excel VBA Programming For Dummies</a> （425页英文PDF，6.18Mb） </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/regex-in-excel-vba.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
