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

<channel>
	<title>我爱正则表达式</title>
	<atom:link href="http://iregex.org/feed" rel="self" type="application/rss+xml" />
	<link>http://iregex.org</link>
	<description>关注正则表达式和搜索引擎</description>
	<lastBuildDate>Mon, 08 Mar 2010 18:32:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>	
<!-- Start Of Script Generated By WP-PostViews Plus -->
<script type='text/javascript' src='http://iregex.org/wp-includes/js/jquery/jquery.js?ver=1.3.2'></script>
<script type="text/javascript">
/* <![CDATA[ */
/* ]]> */
</script>
<!-- End Of Script Generated By WP-PostViews Plus -->
	<item>
		<title>关于从普通文本提取正则表达式的再思考</title>
		<link>http://iregex.org/blog/text-2-regular-expressions-again.html</link>
		<comments>http://iregex.org/blog/text-2-regular-expressions-again.html#comments</comments>
		<pubDate>Mon, 08 Mar 2010 18:32:19 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[应用]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[engine]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[recursive]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=79</guid>
		<description><![CDATA[rex按：写完上一篇文章之后，一直在考虑如何真正实现从普通文本中归纳正则表达式的实现。走了许多弯路，也学了不少知识。例如，perl黑豹书上复杂的数据结构、匿名散列和数组、refenrence；... ]]></description>
			<content:encoded><![CDATA[<blockquote><p><span class="Apple-style-span" style="font-style:normal">rex按：写完</span><a href="http://iregex.org/blog/literal-text-to-regex.html" id="vt:b" title="个人应用之明文字串到正则"><font class="Apple-style-span" color="#474747"><span class="Apple-style-span" style="font-style:normal">上一篇</span></font></a><span class="Apple-style-span" style="font-style:normal">文章之后，一直在考虑如何真正实现从普通文本中归纳正则表达式的实现。走了许多弯路，也学了不少知识。例如，perl黑豹书上复杂的数据结构、匿名散列和数组、refenrence；紫龙书上的状态机的构造，数据结构上图论的知识，都是很有用的。另外还新学了</span><a href="http://www.graphviz.org/" id="mk58" title="graphviz"><span class="Apple-style-span" style="font-style:normal">graphviz</span></a><span class="Apple-style-span" style="font-style:normal">的用法。以前觉得很神秘，不过一用才发现很直观。本文的插图是使用</span><a href="http://graph.gafol.net/create" id="a1la" title="online版本的graphviz"><font class="Apple-style-span" color="#474747"><span class="Apple-style-span" style="font-style:normal">online版本的graphviz</span></font></a><span class="Apple-style-span" style="font-style:normal">画的。</p>
<p> 除了本文的这种实现方法（基于图），我还使用另一种方式实现了，很简单：基于关键词。具体作法是，逐一读取每一行文本，使用\s+等将其split开，形成array；然后再对所有的array进行求交集的操作（使用hash），得到每一行都有的关键词；然后按从左到右的顺序建立这覆的正则式^(.*?)keyword1(.*?)keyword2&#8230;.keywordN(.*?)$，再分别匹配每一行文本，得到hash的hash表，或者array的array，转置，并列输出，得到^(option1|option2&#8230;)keyword1(option..)&#8230;$这样的正则式。最后作为验证，再将所最终生成的正则与每一行匹配测试一下。</p>
<p> 这样以词为单位做完之后，再逐个字母地分隔开来，递归地处理</span><font class="Apple-style-span" color="#474747"><span class="Apple-style-span" style="font-style:normal">(option1|option2&#8230;)的部分。先是单词级，再是字母级，有利于先在最大程度上找出重复的内容；而且粗化和细化的处理过程，思路是一致的，粒度不同罢了。</p>
<p> 新手请自重，高手请赐教，我的思路未必是正确或最优的。</span></font></p></blockquote>
<h3><font class="Apple-style-span"><span class="Apple-style-span" style="background-color:#b6d7a8">问题 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span></font></h3>
<h3 style="margin-left:0px;margin-right:0px"><font class="Apple-style-span" style="margin-left:0px;margin-right:0px">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</font></h3>
<div>有文本文件text.txt，内容如下：</div>
<blockquote>
<div>this is a red fox</div>
<div>this is a blue firefox</div>
<div>this is a pig</div>
<div>a red fox</div>
</blockquote>
<div>请写一则程序，根据文本内容，自动构造（比较合理的）正则表达式，使之能够匹配文件中<b>每一行</b>文本。</div>
<p></p>
<h3 style="margin-left:0px;margin-right:0px"><font class="Apple-style-span" size="5"><font class="Apple-style-span"><span class="Apple-style-span" style="background-color:#b6d7a8">标准正则 &nbsp; &nbsp; &nbsp; &nbsp;</span></font><font class="Apple-style-span"><span class="Apple-style-span" style="background-color:#b6d7a8">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   </span></font> &nbsp;&nbsp;</font></h3>
<h3 style="margin-left:0px;margin-right:0px"><font class="Apple-style-span" size="2">有两种极端的解法是不可取的：</font></h3>
<ol>
<li><font class="Apple-style-span" color="#FF00FF">^.*$</font></li>
<li><font class="Apple-style-span" color="#FF00FF">^(this is a red fox|this is a blue firefox|this is a pig|a red fox)$</font></li>
</ol>
<p> 第一种失之于太宽泛，第二种失之于太狭隘。太宽泛则泥沙俱下，无论什么文本都能匹配；太狭隘则僵化死板，缺乏灵活性。好的正则表达式源于例文本（从例文本中提取规律），又高于例文本（能匹配同规律的其它文本）。匹配什么，排除什么，都有定则，所谓“君子有所为而有所不为”，指的就是这种情况（貌似跑题了:)）。</p>
<p></p>
<div>那么，如何是比较靠谱的正则表达式呢？以上文的例子而言，可以是：</div>
<div><font class="Apple-style-span" color="#FF00FF">^(this is )?a (red fox|blue firefox|pig)$</font></div>
<p></p>
<div>现在我们向着标准答案出发。</div>
<p></p>
<h3><font class="Apple-style-span"><span class="Apple-style-span" style="background-color:#93c47d">思路 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span></font></h3>
<p></p>
<div>任何复杂的电路图，都可以拆分为三种简单的关系：串联，并联，短路。正则表达式也同理。</div>
<p></p>
<p>既然是一条正则匹配所有的文本，那么这条正则（记为<font class="Apple-style-span" color="#FF00FF">$re</font>）也应该匹配第一行文本。</p>
<p>第一行文本为this is a red fox。那么，从<font class="Apple-style-span" color="#FF00FF">^this is a red fox$</font>应该是<font class="Apple-style-span" color="#FF00FF">$re</font>的一个（真）子集。它的路径为：<font class="Apple-style-span" color="#FF00FF">&#8220;^&#8221;-&gt;this-&gt;is-&gt;a-&gt;red-&gt;fox-&gt;&#8221;$&#8221;</font>。全部节点之间，是串联关系，从左到右依次排列即可。</p>
<p>示意图如下(可以点击看全尺寸图，下同)：</p>
<p><a href="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309001329.png" style="color:#0071bb;margin-left:0px;margin-right:0px" target="_blank"><img alt="Photobucket" border="0" src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309001329.png" style="border-color:initial;border-style:initial;margin-left:0px;margin-right:0px; width=640px"></a>&nbsp;
</p>
<p>同理，第二行文本也应该是<font class="Apple-style-span" color="#FF00FF">$re</font>的子集。不过，由于已经存在了由<font class="Apple-style-span" color="#FF00FF">^-&gt;this-&gt;is-&gt;a</font>的路径，到a时出现支路，<font class="Apple-style-span" color="#FF00FF">a-&gt;blue-&gt;firefox-&gt;$</font>；</p>
<p>将此路径添加到示意图上，得到：</p>
<p><a href="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309001747.png" style="color:#0071bb;margin-left:0px;margin-right:0px" target="_blank"><img alt="Photobucket" border="0" src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309001747.png" style="border-color:initial;border-style:initial;margin-left:0px;margin-right:0px"></a>&nbsp;
</p>
<p>显而易见，这两条并列的支路，始于a，终于$，可以使用|来并列之。</p>
<p>
</p>
<p>好了，我们总结一下规律：</p>
<div><font class="Apple-style-span" face="arial, sans-serif"><font class="Apple-style-span" color="#000000"><b><font class="Apple-style-span"><span class="Apple-style-span" style="background-color:#6fa8dc">并列</span></font></b>：如果存在A-&gt;B-&gt;C，且同时存在A-&gt;D-&gt;C，则B与D之间是并联关系。即出发点相同，结束点相同，且出发点与结束点之间各有一个以上的节点。并列使用括号来表示，之间以|分隔。例如，对于<font class="Apple-style-span" face="arial, sans-serif"><font class="Apple-style-span" color="#000000">A-&gt;B-&gt;C，A-&gt;D-&gt;C，则可以使用A(B|D)C来表示其正则关系。</font></font></font></font>
</div>
<p></p>
<div><font class="Apple-style-span" face="arial, sans-serif"><font class="Apple-style-span" color="#000000">为什么要强调是一个以上节点呢？这里先卖个关子。请继续阅读。</font></font></div>
<p>
 再往下，this is a pig，同理，只需要在原图基础上添加<font class="Apple-style-span" color="#FF00FF">a-&gt;pig-&gt;$</font>的支路即可。此时图示如下：</p>
<p><a href="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309002851.png" style="color:#0071bb;margin-left:0px;margin-right:0px" target="_blank"><img alt="Photobucket" border="0" src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309002851.png" style="border-color:initial;border-style:initial;margin-left:0px;margin-right:0px"></a></p>
<div>
最后一条，a red fox。这条貌似复杂，但是只需在<font class="Apple-style-span" color="#FF00FF">^-&gt;a</font>之间新添加了一条路径而已；<font class="Apple-style-span" color="#FF00FF">a-&gt;red-&gt;fox-&gt;$</font>之间原有路径，可以继续使用。此时，得到完整的示意图如下：</div>
<p><a href="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309003225.png" style="color:#ed1e24;margin-left:0px;margin-right:0px;text-decoration:none" target="_blank"><img alt="Photobucket" border="0" src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309003225.png" style="border-color:initial;border-style:initial;margin-left:0px;margin-right:0px"></a>&nbsp;<br />
&nbsp;此时，观察可知，一种新的情况出现了。同时存在<font class="Apple-style-span" color="#FF00FF">^-&gt;a</font>，和<font class="Apple-style-span" color="#FF00FF">&#8220;^&#8221;-&gt;this-&gt;is-&gt;a</font>两条路径。想一下初中物理电路图，我们可以将这种情况称为“短路”，即，<font class="Apple-style-span" color="#FF00FF">&#8220;^&#8221;-&gt;this-&gt;is-&gt;a</font>这个线路的^、a两个节点之间，添加了一条无障碍通道，它能无视this、is的存在，因此，让<font class="Apple-style-span" color="#FF00FF">this-&gt;is</font>这条路径成为<b>可选项</b>。再总结一下规律：</p>
<p> 如果有A-&gt;B-&gt;&#8230;C-&gt;D的路径，且有A-&gt;D的路径，则称A-&gt;D之间存在短路，此时,B-&gt;&#8230;-&gt;C可以用(B-&gt;&#8230;-&gt;C)?来表示(就是用括号来表示被短路的部分，问号表示短路之)。</p>
<div>顶点A,D之间，最多存在一个短路关系。但是可以有1或更多条并列的关系存在。</div>
<p></p>
<div>好了，分析结束，得到这样的正则式：</div>
<div><font class="Apple-style-span" color="#FF00FF">^(this is )?a (red fox|blue firefox|pig)$</font></div>
<p>
这也就是为什么上文要强调是一个节点的缘故。</p>
<div>如果我们再精益求精的话，可以对<font class="Apple-style-span" color="#FF00FF">red fox|blue firefox|pig</font>这部分<b><font class="Apple-style-span" color="#FF00FF">递归地</font></b>进行上述分析过程，进而得到<font class="Apple-style-span" color="#FF00FF"> (red |blue fire)fox|pig</font>这样的结果。</p>
<h3><font class="Apple-style-span"><span class="Apple-style-span" style="background-color:#b6d7a8">实现 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span></font></h3>
<div>思路有了，编程就简单了。perl中，固然可以使用比较简洁的hash表来表示链表之间的关系：</div>
<div>例如：</div>
<p></p>
<div>my $hash;</div>
<p>
</div>
<div style="margin-left:0px;margin-right:0px">$$hash{&#8220;^&#8221;}{&#8220;this&#8221;}{&#8220;is&#8221;}{&#8220;a&#8221;}{&#8220;red&#8221;}{&#8220;fox&#8221;}{&#8220;\$&#8221;}=&#8221;";</div>
<div>$$hash{&#8220;^&#8221;}{&#8220;this&#8221;}{&#8220;is&#8221;}{&#8220;a&#8221;}{&#8220;blue&#8221;}{&#8220;firefox&#8221;}{&#8220;\$&#8221;}=&#8221;";
</div>
<p> &#8230;</p>
<div>但是，节点的增删修改都是麻烦事。（我在hash迷宫中lost了很久才爬出来）</div>
<p></p>
<div>抽空补了一下<b>有向图</b>的知识，觉得可以简化问题如下。</div>
<p>
<a href="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309003225.png" style="color:#ed1e24;margin-left:0px;margin-right:0px;text-decoration:none" target="_blank"><img alt="Photobucket" border="0" src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20100309003225.png" style="border-color:initial;border-style:initial;margin-left:0px;margin-right:0px;width=650px"></a>&nbsp;</p>
<p>上图其实是一个有向图，只需记录所有的顶点集合，路径集合，再来求各路径之间的关系；最后打印输出，即是所求。</p>
<div>顶点集合为：</div>
<p></p>
<div><font class="Apple-style-span" color="#FF00FF">(^, this, is, a, red, fox, blue, firefox, pig, $);</font></div>
<p></p>
<div>通路关系集合为：</div>
<p></p>
<div><font class="Apple-style-span" color="#FF00FF">(^-&gt;this, this-&gt;is,&#8230;)</font></div>
<p>
这两个集合在读取文本文件行的时候可以一次性建立。不复杂。关键是关系的确立。</p>
<div>再次总结，如下：</div>
<ul>
<li>从一个顶点A出发的N条支路必定汇合（只是有时是同一个点，有时不在同一点而已。本文给出的例子是最简单的情况，这里可以假设为汇合到同一点）于M点。</li>
<li>这N条路中，每一条路径的长短以经过的节点个数来计算。例如上图中，^到a有一条路，上面的路径为2，下面的路径为0。</li>
<li>短的支路决定了这N条支路的关系。</li>
<li>长度为任意两点之间，最多只可能有一条长度为0的边。</li>
<li>如果存在长度为0的边，则其余的同级的支路被短路。</li>
<li>长度不为0的N-1条支路之间是并列关系。</li>
<li>整个图始于^，终于$。</li>
</ul>
<div>这些条件、判断，均可以细化为函数。具体的程序从略。</div>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/text-2-regular-expressions-again.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>个人应用之明文字串到正则</title>
		<link>http://iregex.org/blog/literal-text-to-regex.html</link>
		<comments>http://iregex.org/blog/literal-text-to-regex.html#comments</comments>
		<pubDate>Wed, 10 Feb 2010 08:50:15 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[应用]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=78</guid>
		<description><![CDATA[近来工作中需要将某种明文字串转为简单的正则式。手动做当然可以，但是大量重复性的劳动，自然是交给机器处理为好。昨晚写了一款这样的脚本，放在这里。因为是处理我自己的工作的脚... ]]></description>
			<content:encoded><![CDATA[<p>近来工作中需要将某种明文字串转为简单的正则式。手动做当然可以，但是大量重复性的劳动，自然是交给机器处理为好。昨晚写了一款这样的脚本，放在这里。因为是处理我自己的工作的脚本，贴在这里仅作记录和存档之用，可能对别人没什么实际作用。当然，从现有的明文字串到正则式的转换，应该是个不错的题目，有兴趣朋友的可以深究。</p>
<p>值得一提的是，代码中用了<font color="#FF00FF">$&#038;, (?{})</font> 这样的<font color="#FF00FF">perl only</font>的东东，明晰了思路，简化了代码。如果不使用这种特性的话，代码要<strong>长5倍</strong>。另外，据说从效率上来说，<font color="#FF00FF">use English</font>之后，使用<font color="#FF00FF">$MATCH</font>比直接使用<font color="#FF00FF">$&#038;</font><strong>快5倍</strong>。但是对于即输入即执行的命令行程序来说，<font color="#FF00FF">$&#038;</font>已经足够好。</p>
<p>实际应用一例：</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">perl hash2re.pl H:aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA0.zip/H:aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA-0/aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA-0/aaa/Aaaaa/aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA-0.exe
RE 1:   ^[a-z]{3}-[A-Z][a-z]{3}-[A-Z][a-z]{3}[A-Z][a-z]{6}[A-Z][a-z]{7}-[A-Z]{3}[0-9]\.zip$
        Matches: &quot;aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA0.zip&quot;
&nbsp;
RE 2:   ^[a-z]{3}-[A-Z][a-z]{3}-[A-Z][a-z]{3}[A-Z][a-z]{6}[A-Z][a-z]{7}-[A-Z]{3}-[0-9]$
        Matches: &quot;aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA-0&quot;
&nbsp;
RE 3:   ^[a-z]{3}-[A-Z][a-z]{3}-[A-Z][a-z]{3}[A-Z][a-z]{6}[A-Z][a-z]{7}-[A-Z]{3}-[0-9]$
        Matches: &quot;aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA-0&quot;
&nbsp;
RE 4:   ^[a-z]{3}$
        Matches: &quot;aaa&quot;
&nbsp;
RE 5:   ^[A-Z][a-z]{4}$
        Matches: &quot;Aaaaa&quot;
&nbsp;
RE 6:   ^[a-z]{3}-[A-Z][a-z]{3}-[A-Z][a-z]{3}[A-Z][a-z]{6}[A-Z][a-z]{7}-[A-Z]{3}-[0-9]\.exe$
        Matches: &quot;aaa-Aaaa-AaaaAaaaaaaAaaaaaaa-AAA-0.exe&quot;</pre></div></div>

<p>源码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#   by rex zhang </span>
<span style="color: #666666; font-style: italic;">#   Feb 09 2010 in Shanghai</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#   usage: split and regexize hashed filename</span>
<span style="color: #666666; font-style: italic;">#</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$lines</span><span style="color: #339933;">=</span><span style="color: #0000ff;">$ARGV</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$lines</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #666666; font-style: italic;">#(C:[^/]+)#)</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #0000ff;">$c</span><span style="color: #339933;">=</span><span style="color: #0000ff;">$1</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$lines</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/$c//</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;ClearText Filename Ignored:<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\&quot;</span>$c<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">@array</span><span style="color: #339933;">=</span><span style="color: #000066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">m</span><span style="color: #339933;">!</span><span style="color: #0000ff;">\s</span><span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">?:</span>\<span style="color: #339933;">/|</span>H<span style="color: #339933;">:</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #0000ff;">\s</span><span style="color: #339933;">*!,</span> <span style="color: #0000ff;">$lines</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$counter</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #0000ff;">$line</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">@array</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">next</span> <span style="color: #b1b100;">if</span> <span style="color: #b1b100;">not</span> <span style="color: #0000ff;">$line</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$re</span><span style="color: #339933;">=</span><span style="color: #0000ff;">$line</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #0000ff;">$len</span><span style="color: #339933;">;</span>    
&nbsp;
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/(?=[.\[\]()])/\\/g</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/\?/./g</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/0+(?{ $len=length($&amp;)})/[0-9]\{$len\}/g</span><span style="color: #339933;">;</span> 
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/A+(?{ $len=length($&amp;)})/[A-Z]\{$len\}/g</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/a+(?{ $len=length($&amp;)})/[a-z]\{$len\}/g</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/(.)\1+(?{ $len=length($&amp;)})/$1\{$len\}/g</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/\{1\}//g</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$re</span> <span style="color: #339933;">=</span>  <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\^</span>$re<span style="color: #000099; font-weight: bold;">\$</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #0000ff;">$counter</span><span style="color: #339933;">++;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$line</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/$re/</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;RE $counter:<span style="color: #000099; font-weight: bold;">\t</span>$re<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>Matches: <span style="color: #000099; font-weight: bold;">\&quot;</span>$line<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>    
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;RE $counter:<span style="color: #000099; font-weight: bold;">\t</span>$re<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>Failed: <span style="color: #000099; font-weight: bold;">\&quot;</span>$line<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/literal-text-to-regex.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>统计重复文本行的两种方法</title>
		<link>http://iregex.org/blog/get-duplicated-lines.html</link>
		<comments>http://iregex.org/blog/get-duplicated-lines.html#comments</comments>
		<pubDate>Sat, 06 Feb 2010 07:09:43 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[应用]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=77</guid>
		<description><![CDATA[假设样本文件a.txt内容如下：

hello world!
hello world!
I love regex.
hello world!
I love regex.
hello world!

简单观察可知，hello world!共重复4行；I love regex.重复2行。如何使用正则表达式来写一个程序，统计这... ]]></description>
			<content:encoded><![CDATA[<p>假设样本文件<font color="#FF00FF">a.txt</font>内容如下：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">hello world!
hello world!
I love regex.
hello world!
I love regex.
hello world!</pre></div></div>

<p>简单观察可知，<font color="#FF00FF">hello world!</font>共重复4行；<font color="#FF00FF">I love regex.</font>重复2行。如何使用正则表达式来写一个程序，统计这些数据呢？因为现实中需要统计的文件，绝非是只凭肉眼就能观察出来。我想到了两种方法，第一种方法，是依赖于正则表达式（否则这篇文章也不会贴在这里）；第二种，hash表做主角，正则表达式作绿叶。</p>
<h3>正则表达式的解法</h3>
<p>思路是：对于任何一行文本，如果后面若干行[0～EOF）之后，如果存在相同的文本行，则记下该行内容，统计出现次数；然后删除这样的文本行，再进行下一行的统计。输出统计结果。</p>
<p>下面是相应的perl程序，附注释。</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl </span>
<span style="color: #666666; font-style: italic;">#usage:  ./dup_re.pl &lt;a.txt</span>
&nbsp;
<span style="color: #000066;">undef</span> <span style="color: #0000ff;">$/</span><span style="color: #339933;">;</span>           <span style="color: #666666; font-style: italic;"># enable &quot;slurp&quot; mode</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$file</span> <span style="color: #339933;">=</span> <span style="color: #009999;">&lt;STDIN&gt;</span><span style="color: #339933;">;</span>          <span style="color: #666666; font-style: italic;"># whole file now here</span>
&nbsp;
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$file</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span>
    <span style="color: #339933;">/</span>                   <span style="color: #666666; font-style: italic;">#for each line;</span>
        <span style="color: #339933;">^</span><span style="color: #0000ff;">\s</span><span style="color: #339933;">*</span>            <span style="color: #666666; font-style: italic;">#ignore the whitespaces at both ends; </span>
        <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\S</span><span style="color: #339933;">.*?</span><span style="color: #009900;">&#41;</span>         <span style="color: #666666; font-style: italic;">#get the line content, save to $1;</span>
        <span style="color: #0000ff;">\s</span><span style="color: #339933;">*</span>$            <span style="color: #666666; font-style: italic;">#ignore empty lines by using \S</span>
        <span style="color: #339933;">.*?</span>             <span style="color: #666666; font-style: italic;">#check if there is the same pattern of $1</span>
        <span style="color: #339933;">^</span><span style="color: #0000ff;">\s</span><span style="color: #339933;">*</span>\<span style="color: #cc66cc;">1</span><span style="color: #0000ff;">\s</span><span style="color: #339933;">*</span>$              <span style="color: #666666; font-style: italic;">#after 0 or more lines;</span>
    <span style="color: #339933;">/</span>smx<span style="color: #009900;">&#41;</span> 
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$line</span><span style="color: #339933;">=</span><span style="color: #0000ff;">$1</span><span style="color: #339933;">;</span>                        
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$count</span><span style="color: #339933;">=</span> <span style="color: #0000ff;">$file</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/$line//g</span><span style="color: #339933;">;</span>     <span style="color: #666666; font-style: italic;">#delete the duplicated lines</span>
                       <span style="color: #666666; font-style: italic;">#save the number to $count;</span>
                                       <span style="color: #666666; font-style: italic;">#ignore empty lines</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$count</span><span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;times:<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$line</span><span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Hash表解法</h3>
<p>这种方法，受益于perl语言本身的强大的hash表功能。思路如下：</p>
<ul>
<li>建立空的hash表；</li>
<li>逐行读取文件；</li>
<li>以文本内容为key，插入到表中来。如果是首次出现，value为0，否则value++。</li>
<li>输出hash表中value>=2的记录。</li>
</ul>
<p>Perl程序：</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span>
<span style="color: #666666; font-style: italic;">#usage:  ./dup_hash.pl a.txt</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">%hash</span><span style="color: #339933;">=</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;&gt;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/^\s*(\S.*?)\s*$/</span><span style="color: #009900;">&#41;</span>           <span style="color: #666666; font-style: italic;">#ignore whitespaces at both ends; </span>
   <span style="color: #009900;">&#123;</span>                                <span style="color: #666666; font-style: italic;">#ignore empty lines by using \S</span>
        <span style="color: #0000ff;">$hash</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$1</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">++;</span>                <span style="color: #666666; font-style: italic;">#save the line to $1, and count the time it appears</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#sort the hash by values; </span>
<span style="color: #b1b100;">foreach</span> <span style="color: #0000ff;">$key</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">sort</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">$hash</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$b</span><span style="color: #009900;">&#125;</span> <span style="color: #339933;">&lt;=&gt;</span> <span style="color: #0000ff;">$hash</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$a</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#125;</span> <span style="color: #000066;">keys</span> <span style="color: #0000ff;">%hash</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$hash</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$key</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">&gt;=</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span>             <span style="color: #666666; font-style: italic;">#only print the lines that duplicates;</span>
    <span style="color: #009900;">&#123;</span>                               <span style="color: #666666; font-style: italic;">#for all results, just remove the 'if' line</span>
       <span style="color: #000066;">printf</span> <span style="color: #ff0000;">&quot;%d times:<span style="color: #000099; font-weight: bold;">\t</span>%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$hash</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$key</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$key</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>结果</h3>
<p>上面的程序分别保存为dup_re.pl，dup_hash.pl。由于程序对于外部文件的读取的方法不同，运行方式也有差别，详见下图：<br />
<img src="http://public.bay.livefilestore.com/y1p84mh-sSb8s2jIOokB1tAnVJQnNdmS1ir1v9A0nRbWPPZ6AdIQV896FPpKr_LNzQvJ6kJQ-Ue94wHK8LVscG8uQ/20100206_144726.png" alt="我爱正则表达式|统计重复文本行的两种方法" /></p>
<h4>Update</h4>
<p>忽然想到，如果要让这脚本更有效，可以指定忽略大小写，忽略单词间多个空格的情况，使得<font color="#FF00FF">Hello world!</font>与<font color="#FF00FF">      　　hello　　       WORLd!   </font>被视为重复行。测试了一下，正则式没让我失望。</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/get-duplicated-lines.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>由正则式反推文本:REExtractor</title>
		<link>http://iregex.org/blog/reextractor.html</link>
		<comments>http://iregex.org/blog/reextractor.html#comments</comments>
		<pubDate>Tue, 02 Feb 2010 09:12:35 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[应用]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[REExtractor]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=76</guid>
		<description><![CDATA[发现一款简单有趣的正则表达式应用：REExtractor，作用是输入正则表达式，输出符合正则式描述的文本。作者给的介绍是
Generate all possibilities of Regular Expression，即生成正则表达式的所有可能性... ]]></description>
			<content:encoded><![CDATA[<p>发现一款简单有趣的正则表达式应用：<a id="f-4f" href="http://re2form.appspot.com/" title="我爱正则表达式|由正则式反推文本">REExtractor</a>，作用是输入正则表达式，输出符合正则式描述的文本。作者给的介绍是<br />
Generate all possibilities of Regular Expression，即生成正则表达式的所有可能性。不过，理论上可以做到，执行时却有限制。</p>
<h3>一些限制</h3>
<ol>
<li>平台是GAE，语言是python，因此用的是python正则。或需代理才能访问使用。</li>
<li>支持的元字符或缩写：<font class="Apple-style-span" color="#FF00FF">(), [],{m,n},{n},|,\w,\d</font>。如果需要用到这些字符的字面值，请使用反斜线转义之。其中这里的\w等同于<font class="Apple-style-span" color="#FF00FF">[a-zA-Z0-9]</font>，为62个字符之一，而不是通常意义上的包括下划线在内的<font class="Apple-style-span" color="#FF00FF">[_a-zA_Z0-9]</font>，63字符之一。但是可以用<font class="Apple-style-span" color="#FF00FF">[_\w]</font>来代替，没问题的。</li>
<li>不支持的元字符：<font class="Apple-style-span" color="#FF00FF">.(点号),^,$,\b,\D,\W,\1&#8230;（后向引用）, (?=&#8230;), (?!&#8230;), (?&lt;=&#8230;), (?&lt;!&#8230;)</font>等。</li>
<ul>
<li>如果出现<font class="Apple-style-span" color="#FF00FF">.</font>点号，则直接输出。</li>
<li>如果使用<font class="Apple-style-span" color="#FF00FF">^, $, \b, \1, (?=&#8230;), (?!&#8230;), (?&lt;=&#8230;), (?&lt;!&#8230;)</font>， 程序无视之。</li>
<li>如果使用<font class="Apple-style-span" color="#FF00FF">\D或\b或[^]</font>，则程序会报错。原因是范围太宽。</li>
</ul>
<li>不支持可能性在1000条以上结果的正则表达式。例如，<font class="Apple-style-span" color="#FF00FF">\w{2}</font>，因为它的可能性是62×62。但是你可以使用\w\d，因为它的可能性是62×10。</li>
</ol>
<h3>它能做什么</h3>
<p><a href="http://iregex.org/blog/REExtractor.html" target="_blank" title="我爱正则表达式|由正则式反推文本"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100202170343.jpg" border="0" alt="我爱正则表达式|由正则式反推文本"></a><br />
好吧，虽然限制多多，但是你仍然可以拿它来做一些有趣的应用。下面略举两例。</p>
<ul>
<li>生成一些简单的邮箱地址。试一下这条正则式：<font class="Apple-style-span" color="#FF00FF">[abc]{3}\d@1(26|63).com</font> ，它生成540条邮箱地址。</li>
<li>生成一些人名。试一下这条正则式：<font class="Apple-style-span" color="#FF00FF">张[小大勇赞强战海][虎猫龙彪平]</font>。它生成35条人名。是的，它支持中文，并且每个中文字都可以当成一个字符来应用。如果你家要添一个宝宝，可以将一些可能的字排列一下，看看哪些组合比较赏心、顺口，再从中选择一个。</li>
</ul>
<p>平心而论，上面的这些小应用，当然可以直接编程实现，限制更少，更灵活，更强大。但是有必要每次都开编译器么？尝试一下这款小程序，也挺有趣的。而且，上一节中提及的一些限制，其实也是蛮有道理的。毕竟从正则式反推文本，用不到大多数的零宽断言（不过<font class="Apple-style-span" color="#FF00FF">\1</font>这种反向引用应该挺常用的，却不支持）。当作一个小玩具就好。</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/reextractor.html/feed</wfw:commentRss>
		<slash:comments>2</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><p>rex译注：在《Programming Perl》第三版第五章，讲了正则匹配的六条规则，深入，透彻，但是不易理解。可以将本文当作是该章的简化版。另外，一定的正则式调试经验也有助于理解正则式的匹配过程。可以参考《Programming Perl》第五章“正则表达式编译器”一节，或阅读这篇文章《<a href="http://perl.active-venture.com/pod/perldebguts-debugregexp.html">Debugging Regular Expressions</a>》。建议阅读例程序时，先默想输出结果，然后再上机测试，最后再看本文的答案。
</p></blockquote>
<p>经常见到关于正则表达式“偏好”的讨论，即，正则表达式引擎“喜欢”更长的、更短的，还是最左端的匹配。</p>
<p>事实非常简单：正则表达式引擎总是返回它所匹配到的第一个结果，如果你理解了正则表达式尝试匹配的顺序，你就再也不会对找到哪一个匹配而困惑了。</p>
<p>下面是一些简单规则（次序无关），阐释正则引擎尝试匹配的顺序。</p>
<h3>1．从最左端的字符开始</h3>
<p>引擎从目标字串的第一个字符开始，对正则模式进行匹配测试。只有当在第一个字符位置测试完整个正则模式且匹配失败时，引擎才会移动到目标字串的下一个字符，重新开始匹配测试。这样依次测试，直到字串的结束位置。</p>
<p>例子：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><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>
  <span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>其输出结果是“<font color="#ffffff">The</font>”（请先自行猜测，再使用鼠标选定，查看结果；下同。），原因是匹配是从字串的最左端开始的。这个单词之后，还有一个更长的单词可以匹配，但是正则引擎却对其视而不见：只要从字串开始处进行匹配且成功，它就返回这个结果，匹配过程就结束了。</p>
<blockquote><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>2. 最左边的备选项优先</h3>
<p>如果正则模式中含备选项，那么首先测试左边的选项。如果最左侧的备选项成功匹配，那么就继续使用剩余的正则表达式剩余的字串进行匹配测试；只有在最左边的备选项不能匹配时才依次尝试下一个备选项。</p>
<p>例子：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><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>
 <span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></pre></td></tr></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>3. 贪婪模式</h3>
<p>对于任何常规的量词（即? * + {1,3}），引擎首先会尝试允许范围内最大数量的重复次数（如果实际文本不足，则尽可能多地重复），然后继续使用剩余的正则表达式剩余的字串进行匹配测试。只有当剩余的正则匹配失败时，引擎才不情愿地“吐出”一次重复的文本，尝试进行后续的匹配，直到匹配成功，或到达允许重复的最小次数。<br />
例子：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><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>
<span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></pre></td></tr></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><p>Rex: 如果我们想把下面的英文字串</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">At this point the remaining pattern matches, so this is the match returned</pre></div></div>

<p>提取出最后一个单词和其它部分，应该怎样写正则呢？(.*)(\w+)$吗？这样的话，$2中只有d这个字母。正确的写法包括：</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><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>$        <span style="color: #666666; font-style: italic;"># .*先用完整个字符，再一个字符一个字符地回退，直到遇到一个单词边界，然后开始找\w+。</span></pre></div></div>

</blockquote>
<h3>4. 懒惰模式</h3>
<p>在量词之后加上问号?（即?? *? +? {1,3}?），就由贪婪模式变为懒惰模式，匹配的过程也随之改变：引擎先尝试允许范围内最少次数的重复，随即使用后续的正则对后续的字串作匹配测试。只有当后续的正则匹配失败时，引擎才懒洋洋地再吃进一次重复，再进行后续匹配测试，直到匹配成功，或到达所允许的匹配次数上限。<br />
例子：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><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>
<span style="color: #000066;">print</span> <span style="color: #0000ff;">$match</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>显而易见，输出结果是<font color="#ffffff">bar/baz</font>。匹配过程中，.*?先匹配空字串&#8221;"，然后是&#8221;f&#8221;，&#8221;fo&#8221;，&#8221;foo&#8221;，此时匹配成功，并返回相应结果。</p>
<blockquote><p>Rex:继续思考上节的问题，另一种将At this point the remaining pattern matches, so this is the match returned中最后一个单词与其余部分分开的正则式还可以是：</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #339933;">.*?</span><span style="color: #0000ff;">\w</span><span style="color: #339933;">+</span>$</pre></div></div>

</blockquote>
<h3>5. 正则式各部分的匹配次序：从左到右</h3>
<p>上面一些例子中的暗含前提是正则模式之间的匹配次序是从左到右。因此在“贪婪模式”例子中有两个.*，基于本条规则，只有当第一个.*的条件满足之后，它才会考虑后续的正则表达式该如何匹配。</p>
<h3>6. 嵌套</h3>
<p>其实这只是“从左到右”规则的引申。参见下面的例子：</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><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>
<span style="color: #000066;">print</span> <span style="color: #0000ff;">$inner</span><span style="color: #339933;">;</span></pre></div></div>

<p>其输出结果是“<font color="#ffffff">foo/bar</font>”。正则引擎先遇到外层的量词，意识到该部分正则要尽可能多地重复，然后开始尝试匹配内层的正则。嵌于内层的量词是贪婪的，因此也会尽可能多地重复，它抓到的字串是foo/bar这部分。此时，外层量词没有机会再重复一次匹配了，但是没有关系——整个正则表达式已经成功匹配，因此返回相应结果。</p>
<p>本文概括了绝大部分常规正则表达式的匹配规则。其余不常见的情况，仍需留心（例如锚点，pos()，以及各种各样的零宽断言）。同时，正则表达式优化器有时会让引擎略过某些步骤，但前提条件是目标匹配结果不变。</p>
<blockquote><p>Rex注：将何伟平先生译的《Programming Perl》中的正则匹配规则也抄录在这里。只列提纲，需要详细内容的请自行翻书。</p>
<ul>
<li>规则1：引擎试图尽可能地匹配字符串的左边，这样整个正则表达式按照规则2匹配。<br />
引擎从字符串的第一个字符开始，然后从那里开始尝试匹配整个模式。只有引擎在到达字符串的终点之前先到达模式的终点才是整个模式的匹配。如果匹配，引擎马上退出——它不会继续寻找“更好的”匹配，即便模式可能以几种不同的方式匹配也如此。</li>
<li>规则2：当引擎碰到一个候选集合时（用|符号分隔），不管是在顶层还是在当前“群集”层次中，它都从左向右尝试这些候选项，并且在第一个可以成功完成整个模式匹配的候选项处停止。</li>
<li>规则3：如果根据规则4和5（这样整个正则表达式就可以满足了），某个候选项里顺序列出的每个项都匹配，那么这个候选项就是匹配项。<br />
<blockquote><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>skydrive外链mp3方案</title>
		<link>http://iregex.org/blog/skydrive-mp3-with-google-player.html</link>
		<comments>http://iregex.org/blog/skydrive-mp3-with-google-player.html#comments</comments>
		<pubDate>Sun, 10 Jan 2010 12:29:48 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[应用]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[mp3]]></category>
		<category><![CDATA[skydrive]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=74</guid>
		<description><![CDATA[使用合租空间的独立博客，例如本人，有时想在自己的空间上传mp3，又有版权（美国空间要求趋严）、流量（被迅雷爬到后果很严重）的担心。经过比较，觉得skydrive的空间挺不错的，25G空间，... ]]></description>
			<content:encoded><![CDATA[<p>使用合租空间的独立博客，例如本人，有时想在自己的空间上传mp3，又有版权（美国空间要求趋严）、流量（被迅雷爬到后果很严重）的担心。经过比较，觉得skydrive的空间挺不错的，25G空间，可支持外链。唯一不足之处是操作比较复杂，使用普通的方法不容易批量提取mp3的外链。今天下午做出一种简单易行的方法，可以直接抓取skydrive的公开文件夹里的mp3音乐文件绝对地址并生成Google Player播放代码（因此您就不需要再安装播放mp3的wordpress各种插件了）。所写的php源码一并贴出，有兴趣的自行研究。如果是<a title="我爱正则表达式" target="_blank" href="http://iregex.org" id="n2fe">正则表达式</a>方面的讨论，欢迎跟贴；其它问题恕不回复，见谅。<br />
<span id="more-74"></span><br />
最终效果如下图：</p>
<p><a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110_190109.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a></p>
<p><a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110_183937.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a></p>
<h3>上传</h3>
<p>使用您的liveID在<a title="Skydrive, 25G space!" target="_blank" href="http://skydrive.live.com/" id="nu96">这里</a>登录，然后新建一个<span style="color: rgb(255, 0, 255);">公开</span>的文件夹。之所以要公开，是因为您的mp3是要放在博客上播放的，如果设为私密型，别人就无法欣赏到了。</p>
<p>修改权限的方法见贴图：<br />
<a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110_184249.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a></p>
<p><a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110_184319.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a><br />
上传时，如果是在IE浏览器下，会有提示安装插件，建议安装。这样就可以将待上传的文件批量拖过来上传了。每个文件不超过50M。总文件的大小没有限制。</p>
<h3>指定需要外链的文件地址<br />
</h3>
<p>您可以指定为某个文件夹生成代码，也可以指定文件生成代码。无论哪种方式，都是一个文件对应一段代码，而不是将所有的播放文件生成一个播放列表。您需要先记下该文件的页面地址，然后根据该地址生成代码。</p>
<p>获得单个文件的地址：<br />
<a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110_185001.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a></p>
<p>获取文件夹的地址：<br />
<a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110_184937.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a></p>
<p>拷贝好页面地址备用。</p>
<h3>生成播放代码</h3>
<p>请移步到这里：<br />
<a title="我爱正则表达式" target="_blank" href="http://zh-en.org/livemp3/" id="ikzb">http://zh-en.org/livemp3/</a></p>
<p><a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110201229.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a></p>
<p>输入上一步得到的页面地址，点击OK，大约2秒钟之后，就会看到这样的内容了：</p>
<p>&nbsp;<br />
<a href="http://iregex.org/blog/skydrive-mp3-with-google-player.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/20100110201150.png" alt="我爱正则表式|mp3+Skydrive+GooglePlayer" border="0"></a></p>
<p>将生成的源代码拷贝到wordpress中，就能看到播放器了。</p>
<h3>源代码 </h3>
<p>程序很简单，获得页面地址，使用curl来下载页面，然后使用正则表达式来析取绝对地址，然后生成播放代码，如此而已。其中google player的代码，我是在google reader中读《<a href="http://www.baibanbao.net/">白板报</a>》的海盗电台时发现的。</p>
<p>如果您感兴趣，还可以将此方案扩展，做skydrive图床，原理一致。不赘述。<br />
<br />
php代码如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">//use:  get mp3, wam, wmv direct links from skydrive's public folder, and generate google player code for that.</span>
<span style="color: #666666; font-style: italic;">//author's email&amp;gtalk:   rex [at] zhasm [dot] com</span>
<span style="color: #666666; font-style: italic;">//last edit:    20100110 18:14</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//get the curl handle</span>
<span style="color: #666666; font-style: italic;">//</span>
<span style="color: #000000; font-weight: bold;">function</span> init_curl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$ch</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_RETURNTRANSFER<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_BINARYTRANSFER<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_REFERER<span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;http://skydrive.live.com/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	<span style="color: #666666; font-style: italic;">//curl_setopt($ch, CURLOPT_POST, 1);</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$ch</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">// extract mp3 from the given root page;</span>
<span style="color: #000000; font-weight: bold;">function</span> get_list<span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
&nbsp;
    extract_mp3<span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">//echo $url;</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_URL<span style="color: #339933;">,</span> <span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">//trim the unnecessary parts, for safety</span>
&nbsp;
	<span style="color: #000088;">$links</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^.*?(?=&lt;div id=[\'&quot;]tileView[\'&quot;] class=[\'&quot;]tvContainer[\'&quot;]&gt;)|&lt;div class=&quot;bpViewPermissionsLink&quot;.*$/si'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//you can add your own music filter </span>
	<span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/(?&lt;=&lt;a class=&quot;tvLink&quot;)[^&lt;&gt;]+href=&quot;([^&quot;]+)(?&lt;=mp3|wav|wmv)&quot;/si'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$links</span><span style="color: #339933;">,</span> <span style="color: #000088;">$result</span><span style="color: #339933;">,</span> PREG_PATTERN_ORDER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$r</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
	    extract_mp3<span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span><span style="color: #000088;">$r</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// extract mp3 from the given sub page, generate output code.</span>
<span style="color: #000000; font-weight: bold;">function</span> extract_mp3<span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_URL<span style="color: #339933;">,</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//	&lt;a id=&quot;spPreviewLink&quot; href=</span>
    <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'%(?&lt;=&lt;title&gt;)[^&gt;&lt;]+(?= - Windows Live&lt;/title&gt;)%'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #000088;">$result</span><span style="color: #339933;">,</span> PREG_PATTERN_ORDER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
    <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/(?&lt;=&lt;a\sid=&quot;spPreviewLink&quot;\shref=&quot;)[^&quot;]+(?=&amp;#63;download&quot;)/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #000088;">$result</span><span style="color: #339933;">,</span> PREG_PATTERN_ORDER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$r</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span> 
	    <span style="color: #000088;">$demo</span><span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;    &lt;div class=<span style="color: #000099; font-weight: bold;">\&quot;</span>audio-player-placeholder<span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;
    &lt;embed classname=<span style="color: #000099; font-weight: bold;">\&quot;</span>audio-player-embed<span style="color: #000099; font-weight: bold;">\&quot;</span> type=<span style="color: #000099; font-weight: bold;">\&quot;</span>application/x-shockwave-flash<span style="color: #000099; font-weight: bold;">\&quot;</span> src=<span style="color: #000099; font-weight: bold;">\&quot;</span>https://www.google.com/reader/ui/3247397568-audio-player.swf?audioUrl=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$r</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\&quot;</span> allowscriptaccess=<span style="color: #000099; font-weight: bold;">\&quot;</span>never<span style="color: #000099; font-weight: bold;">\&quot;</span> allowfullscreen=<span style="color: #000099; font-weight: bold;">\&quot;</span>true<span style="color: #000099; font-weight: bold;">\&quot;</span> quality=<span style="color: #000099; font-weight: bold;">\&quot;</span>best<span style="color: #000099; font-weight: bold;">\&quot;</span> bgcolor=<span style="color: #000099; font-weight: bold;">\&quot;</span>#ffffff<span style="color: #000099; font-weight: bold;">\&quot;</span> wmode=<span style="color: #000099; font-weight: bold;">\&quot;</span>transparent<span style="color: #000099; font-weight: bold;">\&quot;</span> flashvars=<span style="color: #000099; font-weight: bold;">\&quot;</span>playerMode=embedded<span style="color: #000099; font-weight: bold;">\&quot;</span> pluginspage=<span style="color: #000099; font-weight: bold;">\&quot;</span>http://www.macromedia.com/go/getflashplayer<span style="color: #000099; font-weight: bold;">\&quot;</span> height=<span style="color: #000099; font-weight: bold;">\&quot;</span>27px<span style="color: #000099; font-weight: bold;">\&quot;</span> width=<span style="color: #000099; font-weight: bold;">\&quot;</span>400px<span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;
    &lt;/div&gt;&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;文件：&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$title</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&lt;br /&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;效果：&lt;br /&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$demo</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&lt;br /&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;代码：&lt;br /&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;textarea cols=&quot;50&quot; rows=&quot;10&quot;&gt;'</span><span style="color: #339933;">,</span><span style="color: #000088;">$demo</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'&lt;/textarea&gt;'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;&lt;br /&gt;<span style="color: #000099; font-weight: bold;">\n</span>&lt;br /&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//get user input</span>
<span style="color: #000088;">$url</span><span style="color: #339933;">=@</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;url&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #000088;">$ch</span><span style="color: #339933;">=</span>init_curl<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=utf-8&quot; /&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$info</span><span style="color: #339933;">=</span>get_list<span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/skydrive-mp3-with-google-player.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[译]递归正则表达式</title>
		<link>http://iregex.org/blog/recursive-regular-expressions.html</link>
		<comments>http://iregex.org/blog/recursive-regular-expressions.html#comments</comments>
		<pubDate>Wed, 16 Dec 2009 15:06:47 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[翻译]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[recursive]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=73</guid>
		<description><![CDATA[原文在此。rex译于2009年12月15～17日，翻译过程中使用的是google docs@prism@firefox@ubuntu 9.10，很爽的体验。感谢余晟老师在正则和翻译方面的悉心指导。

平时我们用到的正则表达式，其实没那么“... ]]></description>
			<content:encoded><![CDATA[<blockquote><p>原文<a title="在此" href="http://www.catonmat.net/blog/recursive-regular-expressions/" id="eklo">在此</a>。<a href="http://iregex.org">rex</a>译于2009年12月15～17日，翻译过程中使用的是google docs@prism@firefox@ubuntu 9.10，很爽的体验。感谢<a href="http://www.luanxiang.org/blog/">余晟</a>老师在正则和翻译方面的悉心指导。</p></blockquote>
<p><a href="http://iregex.org/blog/recursive-regular-expressions.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/yo-dawg-regex.jpg" alt="递归正则表达式" border="0"></a></p>
<p>平时我们用到的正则表达式，其实没那么“规则”。多数编程语言所支持的扩展的正则表达式，其运算能力比起<a title="形式语言理论" href="http://en.wikipedia.org/wiki/Formal_language" id="vcy6">形式语言理论</a>所定义的“<a title="规则" href="http://en.wikipedia.org/wiki/Regular_expression" id="gkvv">规则</a>”正则表达式要强得多。</p>
<blockquote><p>rex注：在这里其实可以看到，如果将<b>正则表达式</b>译为<b>正规表达式</b>，一切就都通顺了：<br />
平时我们用到的正规表达式，其实没那么“正规”。多数编程语言所支持的扩展的正规表达式，其运算能力比起正式语言理论所定义的“正规”正规表达式要强得多。</p>
<p>regular expression的日文是“正规表现”，在鸟哥书中，好像也将其称为正规表达式。<a title="via" href="http://fanfou.alwaysdata.net/status&amp;id=5144919240" id="bg:v">via</a></p>
</blockquote>
<p>例如，经常用到的<a title="捕获缓存" href="http://perldoc.perl.org/perlre.html#Capture-buffers" id="emj9">捕获缓存</a>，就是用来帮助我们临时存储任意正则表达式模式，以便重复使用。 又如，“<a title="环视断言" href="http://perldoc.perl.org/perlre.html#Look-Around-Assertions" id="xsz-">环视断言</a>”能让正则表达式引擎在做决定之前先偷偷看看环视一下。这些扩展让正则表达式非常强大，足以描述一些“<a title="上下文无关语法" href="http://en.wikipedia.org/wiki/Context-free_grammar" id="acrs">上下文无关语法</a>”。</p>
<p>Perl语言的正则表达式引擎特性异常丰富，其特征之一是<strong>懒惰正则子表达式</strong>（Lazy regular subexpressions），格式为(??{code})，其中的“code”可以是任意一段perl程序，该子表达式可能匹配时，这段程序就会执行。</p>
<p>我们可以利用这一特征来编写出非常有趣的东西，即将正则表达式自身嵌在它的“code”部分，由此生成<b>递归的正则表达式</b>(a recursive regular expression)！</p>
<p>一直以来，正则表达式无法匹配0<sup>n</sup>1<sup>n</sup>这种表达式，也就是由若干个0以及同等数量的1所组成的字符串。如果使用懒惰正则子表达式，这一经典问题就迎刃而解。</p>
<p>下面是匹配0<sup>n</sup>1<sup>n</sup>字串的perl正则表达式代码。</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #0000ff;">$regex</span> <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">qr/0(??{$regex})?1/</span><span style="color: #339933;">;</span></pre></div></div>

<blockquote><p>rex注：紫龙书第四章有云：“文法是比正则表达式表达能力更强的表示方法。每个可以使用正则表达式描述的构造，都可以使用文法来描述，但是反之不成立。换句话说，每个正则语言都是一个上下文无关语言，但是反之不成立。”书中交待的正则，也应该是指的常规正则表达式，而非现代语言中的扩展的正则表达式。一般使用正则表达式来构造小部件，而使用文法来组建语言框架。
</p></blockquote>
<p>此正则表达式匹配一个字符0，之后是正则表达式自身0或1次，之后是字符1。如果正则表达式自身部分不能匹配，那么它只能匹配01；如果自身部分可以匹配，则正则表达式匹配的是00($regex)?11，此时若不能匹配自身则结果是0011，若可以匹配就是000($regex)?111，……依次顺延。</p>
<p>下面是匹配0<sup>50000</sup>1<sup>50000</sup>的Perl程序：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl                                                                                                                         </span>
&nbsp;
<span style="color: #0000ff;">$str</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;0&quot;</span>x50000 <span style="color: #339933;">.</span> <span style="color: #ff0000;">&quot;1&quot;</span>x50000<span style="color: #339933;">;</span>
<span style="color: #0000ff;">$regex</span> <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">qr/0(??{$regex})*1/</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$str</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^$regex$/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;yes, it matches&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;no, it doesn't match&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>现在来看题图所示的Yo Dawg正则表达式。你先猜猜它的作用？正确答案是，它匹配(foo(bar())baz)这样完全嵌套的括号表达式（fully parenthesized expression）或((()()())())这样的平衡括号表达式（balanced parentheses）。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #0000ff;">$regex</span> <span style="color: #339933;">=</span> <span style="color: #000066;">qr</span><span style="color: #339933;">/</span>
  \<span style="color: #009900;">&#40;</span>                 <span style="color: #666666; font-style: italic;"># (1) match an open paren (                               #(1)，此处匹配开括号</span>
    <span style="color: #009900;">&#40;</span>                <span style="color: #666666; font-style: italic;"># followed by                                                      #(2)，紧接着是</span>
      <span style="color: #009900;">&#91;</span><span style="color: #339933;">^</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: #666666; font-style: italic;">#   (3) one or more non-paren character            #(3)，1个或多个非括号字符</span>
    <span style="color: #339933;">|</span>               <span style="color: #666666; font-style: italic;"># OR                                                                    #(4)，或</span>
      <span style="color: #009900;">&#40;</span><span style="color: #339933;">??</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$regex</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>   <span style="color: #666666; font-style: italic;">#   (5) the regex itself                                   #(5)，正则式自身</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span>              <span style="color: #666666; font-style: italic;"># (6) repeated zero or more times                     #(6)，重复0或多次</span>
  \<span style="color: #009900;">&#41;</span>                 <span style="color: #666666; font-style: italic;"># (7) followed by a close paren )                         #(7)，紧接着是闭括号</span>
<span style="color: #339933;">/</span>x<span style="color: #339933;">;</span></pre></td></tr></table></div>

<blockquote><p>rex注：关于Yo Dawg图片的含义，可以参考<a title="这里" href="http://yoyodawgdawg.com/about" id="az.x">这里</a>。基本上是全是“Yo dawg, I herd you like X, so we put a Y in your Y so you can Z while you Z”的结构的配图文字。</p></blockquote>
<p>构造此正则表达式的思路是这样的。对于完全嵌套的括号表达式，它的开始字符是一个开括号。这是最简单的一步，我们直接写出（上面程序中的(1)）。同理，它的结束字符是闭括号，于是得到(7)。现在该动脑筋了，括号中间是什么呢？对，它可以是既不是开括号又不是闭括号的任意字符（第(3)点），<b>也可以是</b>另一个完全嵌套的表达式（即第(5)点）。所有的这些，既可以只匹配0次（第(3)点），以便构造最小的完全嵌套括号表达式()，也可以匹配多次来匹配较复杂的表达式。</p>
<p>去掉 /x 选项（即，不再使用多行风格的注释模式），可以简记为：</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #0000ff;">$regex</span> <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">qr/\(([^()]+|(??{$regex}))*\)/</span><span style="color: #339933;">;</span></pre></div></div>

<p>但是切勿在正式产品中使用这一特性，它太诡异，不好把握。建议使用较稳定成熟的<a href="http://search.cpan.org/dist/Text-Balanced/">Text::Balanced</a> 或 <a href="http://search.cpan.org/dist/Regexp-Common/">Regexp::Common</a> 模块。</p>
<blockquote><p>rex注：对于(??{code})，perl<a href="http://perldoc.perl.org/perlre.html#%28??{-code-}%29">官方的提示</a>是：此正则表达式仅作测试使用，可能有更新而不作提示。代码执行时产生的副作用，因版本而异，运行结果或有不同，取决于正则引擎的后期优化。</p></blockquote>
<p>最后提醒大家，在Perl 5.10中已经可以使用<a title="递归捕获缓存" href="http://perldoc.perl.org/perlre.html#%28?PARNO%29-%28?-PARNO%29-%28?+PARNO%29-%28?R%29-%28?0%29" id="vchb">递归捕获缓存</a>来替代懒惰代码子表达式了，运行结果相同。</p>
<p>下面是匹配0<sup>n</sup>1<sup>n</sup>的递归捕获缓存语法(?N)的实现：</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$rx</span> <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">qr/(0(?1)*1)/</span><span style="color: #339933;">;</span></pre></div></div>

<p>(?1)*的含义是“匹配第一组0或多次”，这里的第一组是指整个正则表达式。</p>
<p>请自行动手，重写平衡括号的正则表达式，当作练习。</p>
<p>祝玩得开心！</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/recursive-regular-expressions.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>抓取页面图片的单行命令</title>
		<link>http://iregex.org/blog/download-images-with-single-line-command.html</link>
		<comments>http://iregex.org/blog/download-images-with-single-line-command.html#comments</comments>
		<pubDate>Mon, 07 Dec 2009 11:58:42 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[应用]]></category>
		<category><![CDATA[cmdline]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[wget]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=72</guid>
		<description><![CDATA[命令如下：


curl -s $URL &#124;perl -nle &#34;print for m{http://[^\&#34;]+(?:jpg&#124;png&#124;gif)}g;&#34;&#124;sort -u &#124;xargs wget


流程：

将包含图片链接的页面（例如http://www.flickr.com/photos/anyaanja/4165312465/sizes/o/... ]]></description>
			<content:encoded><![CDATA[<div>命令如下：<br />
</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">curl <span style="color: #660033;">-s</span> <span style="color: #007800;">$URL</span> <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">perl</span> <span style="color: #660033;">-nle</span> <span style="color: #ff0000;">&quot;print for m{http://[^<span style="color: #000099; font-weight: bold;">\&quot;</span>]+(?:jpg|png|gif)}g;&quot;</span><span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #660033;">-u</span> <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">xargs</span> <span style="color: #c20cb9; font-weight: bold;">wget</span></pre></div></div>

</div>
<p>流程：</p>
<ul>
<li>将包含图片链接的页面（例如http://www.flickr.com/photos/anyaanja/4165312465/sizes/o/ 下载下来，以便析取图片地址。使用的命令是curl -s $URL。这里的地址需要手动替换为你所需要的地址。curl 的-s选项是表明使用silent模式，避免任何输出。
</li>
<li>使用perl解析刚刚下载的页面，找到以http开头，以jpg、png、gif结尾的图片地址。这里的图片类型任意，只要按照类似的语法可以扩展或缩减。perl的-nle选项表示循环读入输入行，搜索相应匹配行，输出相应部分。详细参见<a title="perl one liners" target="_blank" href="http://sial.org/howto/perl/one-liner/" id="x85m">perl one liners</a>。</li>
<li>perl在这里起解析网页的作用。awk应该也有同样的功效，只是个人感觉awk的<a href="http://iregex.org/blog/download-images-with-single-line-command.html">正则表达式</a>功能太弱较弱。
</li>
<li>使用sort -u将生成的url排序。如果有重复项，只保留其一，以免重复下载。</li>
<li>使用wget来下载这些图片到当前目录。由于wget 默认无法接收standard input的输入，因此使用xargs作为中转。</li>
</ul>
<p>
<span style="color: rgb(255, 0, 255);">2009120</span>更新：</p>
<ul>
<li>使用</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">curl <span style="color: #660033;">-s</span> <span style="color: #007800;">$URL</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-o</span> <span style="color: #ff0000;">&quot;http://.*\?\(png\|jpg\)&quot;</span> <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #660033;">-u</span> <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">xargs</span> <span style="color: #c20cb9; font-weight: bold;">wget</span></pre></div></div>

<p>or</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">curl <span style="color: #660033;">-s</span> <span style="color: #007800;">$URL</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #660033;">-o</span> <span style="color: #ff0000;">&quot;http://.*?(png|jpg)&quot;</span> <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #660033;">-u</span> <span style="color: #000000; font-weight: bold;">|</span><span style="color: #c20cb9; font-weight: bold;">xargs</span> <span style="color: #c20cb9; font-weight: bold;">wget</span></pre></div></div>

<p>能实现同样的作用。其中，-o是表示只显示匹配部分，而不必显示整行文本（默认情况下是显示整行文本）；-E 是扩展模式的正则，在此模式下问号、括号、竖线都可直接使用，不必在前边加反斜杠。</li>
<li>使用perl的话，正则表达式部分比较强大，只是命令臃肿；使用grep，灵活小巧，但是有可能无法使用复杂的正则表达式。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/download-images-with-single-line-command.html/feed</wfw:commentRss>
		<slash:comments>0</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>5</slash:comments>
		</item>
		<item>
		<title>效率问题</title>
		<link>http://iregex.org/blog/20091022-efficiency.html</link>
		<comments>http://iregex.org/blog/20091022-efficiency.html#comments</comments>
		<pubDate>Thu, 22 Oct 2009 12:13:46 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[杂项]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=70</guid>
		<description><![CDATA[上周发了篇《两条与密码验证相关的正则表达式问题》。今天看了些python的正则表达式，心血来潮，想看看这几种正则哪种效率较高。代码、运行结果见下。这是为什么呢？

#!/usr/bin/python
import... ]]></description>
			<content:encoded><![CDATA[<p>上周发了篇《<a href="http://iregex.org/blog/2-regex-problems-about-password-verification.html" target="_blank" title="我爱正则表达式|效率问题">两条与密码验证相关的正则表达式问题</a>》。今天看了些python的正则表达式，心血来潮，想看看这几种正则哪种效率较高。代码、运行结果见下。这是为什么呢？</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">fpformat</span>
Regex1 = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;^(?=[0-9a-zA-Z@%&amp;]*<span style="color: #000099; font-weight: bold;">\d</span>)(?=[0-9a-zA-Z@%&amp;]*[a-zA-Z])(?=[0-9a-zA-Z@%&amp;]*[@%&amp;])[0-9a-zA-Z@%&amp;]{8,}$&quot;</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">MULTILINE</span><span style="color: black;">&#41;</span>
Regex2 = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;^(?=.*<span style="color: #000099; font-weight: bold;">\d</span>)(?=.*[a-zA-Z])(?=.*[@%&amp;])[0-9a-zA-Z@%&amp;]{8,}$&quot;</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">MULTILINE</span><span style="color: black;">&#41;</span>
Regex3 = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;^(?![0-9a-z]{8,16}$|[@%&amp;]{8,16}$)[a-z0-9@%&amp;]{8,16}$&quot;</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">IGNORECASE</span> |re.<span style="color: black;">MULTILINE</span><span style="color: black;">&#41;</span> 
&nbsp;
&nbsp;
&nbsp;
TimesToDo = <span style="color: #ff4500;">1250</span><span style="color: #66cc66;">;</span>
TestString = <span style="color: #483d8b;">&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span><span style="color: black;">&#41;</span>:
    TestString += <span style="color: #483d8b;">&quot;aba134babdedfg@&amp;%<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
&nbsp;
StartTime = <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>TimesToDo<span style="color: black;">&#41;</span>:
   Regex1.<span style="color: black;">search</span><span style="color: black;">&#40;</span>TestString<span style="color: black;">&#41;</span>
Seconds = <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - StartTime
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;R1 takes &quot;</span> + <span style="color: #dc143c;">fpformat</span>.<span style="color: black;">fix</span><span style="color: black;">&#40;</span>Seconds,<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot; seconds&quot;</span>
&nbsp;
StartTime = <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>TimesToDo<span style="color: black;">&#41;</span>:
   Regex2.<span style="color: black;">search</span><span style="color: black;">&#40;</span>TestString<span style="color: black;">&#41;</span>
Seconds = <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - StartTime
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;R2 takes &quot;</span> + <span style="color: #dc143c;">fpformat</span>.<span style="color: black;">fix</span><span style="color: black;">&#40;</span>Seconds,<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot; seconds&quot;</span>
&nbsp;
StartTime = <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>TimesToDo<span style="color: black;">&#41;</span>:
   Regex3.<span style="color: black;">search</span><span style="color: black;">&#40;</span>TestString<span style="color: black;">&#41;</span>
Seconds = <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - StartTime
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;R3 takes &quot;</span> + <span style="color: #dc143c;">fpformat</span>.<span style="color: black;">fix</span><span style="color: black;">&#40;</span>Seconds,<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot; seconds&quot;</span></pre></div></div>

<p>运行结果：<br />
<a href="http://iregex.org/blog/20091022-efficiency.html" target="_blank"><img src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20091022.png" border="0" alt="我爱正则表达式|效率问题"></a> </p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/20091022-efficiency.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
