<?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>CNXCT小组的博客 &#187; 正则表达式</title>
	<atom:link href="http://www.cnxct.com/tag/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cnxct.com</link>
	<description>技术这个东西如同一个圆 ,刚开始的时候我们就如同站在圆心,一旦投入学习下去 ,圆就慢慢变大 ,圆的边缘以外也就会越来越大,接触的多了 知道的多了, 就会发现自己真的很无知!</description>
	<lastBuildDate>Tue, 31 Jan 2012 07:56:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>《正则表达式》PPT共享(公司内部培训)</title>
		<link>http://www.cnxct.com/regularexpressions-pptx-pdf-share/</link>
		<comments>http://www.cnxct.com/regularexpressions-pptx-pdf-share/#comments</comments>
		<pubDate>Mon, 18 Jul 2011 03:39:24 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[DFA]]></category>
		<category><![CDATA[NFA]]></category>
		<category><![CDATA[ppt]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[编译原理]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=727</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2011/07/medium2.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2011/07/medium2-150x150.jpg" alt="" title="medium2" width="150" height="150" class="alignleft sided inline" /></a>发明BSD、TCP/IP、csh、vi和NFS的SUN首席科学家Bill Joy说过，在计算机体系结构领域里，缓存是唯一称得上伟大的思想的。其他的一切发明和技术不过是在不同场景下应用这一思想而已。在计算机软件领域里，情形也大体相似。如果罗列这个领域的伟大发明，绝对不超过二十项。这些包括分组交换网络、WEB、lisp、哈希算法、UNIX、编译技术、关系模型、面向对象、XML这些大名鼎鼎的家伙，而正则表达式绝对不应该被漏掉。]]></description>
			<content:encoded><![CDATA[<p>近来我越发懒惰，博客很少更新，最近在公司内部做了一个培训，关于正则表达式的，发到博客里来凑数吧，也算分享给其他朋友了。至于正则表达式的重要性，想必不用我说了吧。</p>
<blockquote><p>发明BSD、TCP/IP、csh、vi和NFS的SUN首席科学家Bill Joy说过，在<em>计算机体系结构领域</em>里，缓存是唯一称得上伟大的思想的。其他的一切发明和技术不过是在不同场景下应用这一思想而已。在<em>计算机软件领域</em>里，情形也大体相似。如果罗列这个领域的伟大发明，绝对不超过二十项。这些包括分组交换网络、WEB、lisp、哈希算法、UNIX、编译技术、关系模型、面向对象、XML这些大名鼎鼎的家伙，而<strong>正则表达式</strong>绝对不应该被漏掉。</p></blockquote>
<p>你还记得大学时候的课程编译原理中提到的 NFA\DFA 吗？还有印象吗？你知道PHP编译器扫描你写的PHP代码字符串的时候，是如何区分哪个是变量，哪个是常量的吗？你知道SQL语法分析器是如何判断你的WHERE条件中出现的SELECT\FROM\ WHERE等关键字是字符串，而不是子查询等关键字的？<br />
你知道.ini配置文件跟xml配置文件对程序来说，是如何扫描解析的吗？他们一样吗？如果你想知道，那你务必的熟悉正则表达式，精通正则表达式。不光能写出正则实现功能，还得能写出高效的正则表达式。(编译原理的课程里，有关于NFA\DNA的大篇幅描述，想写出自己的编程语言，正则是躲不掉的。)</p>
<p>不扯淡了，附PPT吧。<br />
(PPT模版是网上网友的，我是借用他的，其中有几张PPT是直接用他的。很好区分，动画效果很炫的(主要是文字层下的颜色，大约10页吧，简单描述那几页)就是原作者的，其他都是我自己写的。作者信息在PPT最后一页有)<br />
PDF也放出来，效果没PPTX好，很多层都被遮住了。</p>
<p><strong><a href='http://www.cnxct.com/wp-content/uploads/2011/07/regularexpressions.zip'>猛击这里下载《正则表达式》PPTX</a></strong></p>
<p>或者您也可以在线阅读：</p>
<div style="width:425px" id="__ss_9434985"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/cfc4n/ss-9434985" title="正则表达式匹配原理" target="_blank">正则表达式匹配原理</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/9434985" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/cfc4n" target="_blank">cfc4n</a> </div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/regularexpressions-pptx-pdf-share/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>正则表达式与数学（方程式、线性方程）</title>
		<link>http://www.cnxct.com/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e4%b8%8e%e6%95%b0%e5%ad%a6%ef%bc%88%e6%96%b9%e7%a8%8b%e5%bc%8f%e3%80%81%e7%ba%bf%e6%80%a7%e6%96%b9%e7%a8%8b%ef%bc%89/</link>
		<comments>http://www.cnxct.com/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e4%b8%8e%e6%95%b0%e5%ad%a6%ef%bc%88%e6%96%b9%e7%a8%8b%e5%bc%8f%e3%80%81%e7%ba%bf%e6%80%a7%e6%96%b9%e7%a8%8b%ef%bc%89/#comments</comments>
		<pubDate>Sun, 09 Jan 2011 13:21:18 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[分支]]></category>
		<category><![CDATA[回溯]]></category>
		<category><![CDATA[数学]]></category>
		<category><![CDATA[方程式]]></category>
		<category><![CDATA[正则]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[素数]]></category>
		<category><![CDATA[非贪婪]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=687</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2011/01/Lakeside-Sunset-Michigan.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2011/01/Lakeside-Sunset-Michigan-150x150.jpg" alt="" title="清风不识字，何故乱翻书。" width="150" height="150" class="alignleft sided inline" /></a>大清早的打QQ去，收到一位网友的信息。问得是正则表达式判断素数的。去年看到过，没记录下来。
正则表达式如下：【^1?$&#124;^(11+?)\1+$】可以判断素数（换成n个1的形式，n为数字的大小。比如5转换为11111；3转换为111；2转换为11。）]]></description>
			<content:encoded><![CDATA[<p>大清早的打QQ去，收到一位网友的信息。问得是正则表达式判断素数的。去年看到过，没记录下来。<br />
正则表达式如下：</p>
<blockquote><p>^1?$|^(11+?)\1+$ 可以判断素数（换成n个1的形式，n为数字的大小。比如5转换为11111；3转换为111；2转换为11。）</p></blockquote>
<p><strong>什么是素数？</strong><br />
初中学的吧。我们老师当初教我们的是“质数”。看下概念：<br />
质数又称素数。指在一个大于1的自然数中，除了1和此整数自身外，没法被其他自然数整除的数。<br />
换句话说，只有两个正因数（1和自己）的自然数即为素数。比1大但不是素数的数称为合数。1和0既非素数也非合数。</p>
<p><strong>这个正则表达式是什么意思？</strong><br />
【^1?$|^(11+?)\1+$】中间用【|】分开。【|】在正则语法里，表示“或”，作用于其前后两个单元。(还是不明白的看下面，明白的跳过下面这段)</p>
<blockquote><p>比如【ab|cd】可以匹配“ab”、也可以匹配“cd”，意思是除了“ab”就是“bc”，如果想匹配“abd”、“acd”那【|】的作用域得改下，加个范围<br />
改成【a(b|c)】(匹配结果分配组)或者【a(?:b|c)d】(匹配结果不分配组，<a href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/">更高效率</a>)。</p></blockquote>
<p>继续刚刚的正则，分为两个<em>分支</em>，其一为【^1?$】和【^(11+?)\1+$】。其中【^】脱字符在正则语法中，除了在中括号【[]】中都是代表开头的意思，在中括号中的表示非。<br />
第一个分支【^1?$】匹配的是“1”或者“”(空字符串)。<br />
第二个分支【^(11+?)\1+$】，先看下括号内的【(11+?)】匹配的是字符“1”后面接着【1+】就是1到无数个1。后面的【?】问号表示<a href="http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/">非贪婪</a>，就是尽量少的匹配。<br />
接着往后看【\1+】中，【\1】表示引用已匹配的第一个组的结果。也就是第一个【()】括号匹配的结果。同理【\2】就是第二个括号捕获的结果。(小提示：上面提到的【(?:)写法就是不分配组，这样引用的话，就引用不到了】)<br />
【+】就是1到无数个了。这个表达式我们可以这么看。【(11+?)】看成数学中的1+n，其中n为大于0的正整数。外面的【\1+】也就是引用前面这个组的次数。理解成m倍，其中m为大于0的正整数。<br />
那整个表达式就是(1+n)*m。因为n、m都大于0，那么1+n肯定大于1，最小为2，最大为无穷大；m最小为1，最大为无穷大。<br />
那么，一个大于2的正整数的任何大于零的倍数永远都是合数，也就是非素数。</p>
<p>再回过头来看看这个表达式。匹配的分别为0个或1个字符串“1”，也就是数字0，数字1。和其他所有合数。整个表达式，如果成功匹配就是非素数，如果不匹配就是质数。这就是对的了。</p>
<pre class="brush: php; title: ; notranslate">
if (preg_match('/^1?$|^(11+?)\1+$/i', $subject)) {
	#不是素数
} else {
	# 是素数
}
</pre>
<p>小提示：<del datetime="2011-01-09T13:11:29+00:00">此鉴定是否为素数方法仅研究学习用，不能用到正式程序中，字符串过长，会造成非常恐惧大的回溯</del>。</p>
<p>英文博客地址：http://blog.stevenlevithan.com/archives/algebra-with-regexes</p>
<p>在上面的博文中，有提到两个方程式与正则表达式，我们一起来研究下。</p>
<ul>
<li>
二元方程17x + 12y = 51，其表达式【^(.*)\1{16}(.*)\2{11}$】。很好理解。【(.*)】也就是0到无数个【.】点号。（这里是接着上文说的，其实，【.】点号想表示的是字符“1”）<br />
也就是0到无数个1,后面【\1】引用一次。后面【{16}】就是16次。作用于前面的【\1】，也就是16次引用。加上开始的【(.*)】一共正好17次。后面一个就不说了，跟这个一样。<br />
正则引擎会依次尝试【(.*)】中0到无数个字符“1”，0个字符“1”，1个字符“1”，2个字符“1”一直增加的尝试。直到成功，否则要尝试完所有字符“1”的最大个数(这里是51个字符“1”)。</li>
<li>
<p>二、三元方程式11x + 2y + 5z = 115，其表达式为【^(.*)\1{10}(.*)\2{1}(.*)\3{4}$】，理解就跟上面那个一样。注意【\2】、【\3】值得是第2，第3个括号捕获的内容，别看花眼了。
</li>
</ul>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
上面几个有意思的数学题都是将整数转换为对应个数的字符“1”。下面这个，是转换为二进制数的。<br />
先吃饭，以后再写。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e4%b8%8e%e6%95%b0%e5%ad%a6%ef%bc%88%e6%96%b9%e7%a8%8b%e5%bc%8f%e3%80%81%e7%ba%bf%e6%80%a7%e6%96%b9%e7%a8%8b%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于网上流传查找PHP webshell的python脚本中，不严谨的代码</title>
		<link>http://www.cnxct.com/%e5%85%b3%e4%ba%8e%e7%bd%91%e4%b8%8a%e6%b5%81%e4%bc%a0%e6%9f%a5%e6%89%bephp-webshell%e8%84%9a%e6%9c%ac%e4%b8%ad%ef%bc%8c%e4%b8%8d%e4%b8%a5%e8%b0%a8%e7%9a%84%e4%bb%a3%e7%a0%81/</link>
		<comments>http://www.cnxct.com/%e5%85%b3%e4%ba%8e%e7%bd%91%e4%b8%8a%e6%b5%81%e4%bc%a0%e6%9f%a5%e6%89%bephp-webshell%e8%84%9a%e6%9c%ac%e4%b8%ad%ef%bc%8c%e4%b8%8d%e4%b8%a5%e8%b0%a8%e7%9a%84%e4%bb%a3%e7%a0%81/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 15:19:32 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[webshell]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=576</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/nihao_xiatian.jpg"><img class="alignleft sided inline" title="你好，夏天。" src="http://www.cnxct.com/wp-content/uploads/2010/07/nihao_xiatian-150x150.jpg" alt="" width="150" height="150" /></a>不是闲着蛋疼，也不是批评谁，只是不忍心看到不严谨的代码在网上被疯传，误导初学者。以下引用的代码以及思路来自网络，只针对代码，不针对人。如有雷同，纯属巧合。
来自某大牛python版本的检测服务器上PHP代码中webshell的脚本代码片段如下：
findtype=['.php'，'.inc'] #要检查的文件后缀类型
keywords=[ ["eval\(\$\_POST","发现PHP一句话木马！"], ["(system&#124;shell_exec&#124;exec&#124;popen)","发现PHP命令执行函数!"]]
然后，接着是python处理上面列表（数组），把每个列表的第一个元素作为正则表达式内容，然后进行匹配处理的。先看第一个检测“PHP一句话木马”的这个正则。【eval\(\$\_POST】这里转义了字符【_】，字符“_”不是元字符，不需要转义的，其实，转义也无妨，聪明的正则表达式引擎会识别修正的。来说下这个思路的遗漏之处。这里仅仅匹配字符串“eval(”后面的变量“$_POST”，如果是“$_GET”呢？如果是“$_REQUEST”呢？如果程序先把$_POST/$_GET/$REQUEST的key的变量先赋值给一个自定义的变量名，然后在用PHP的“eval”函数执行这个变量呢？是不是就查找不到了？其实，并不需要知道“eval”函数执行的变量名是什么，只要查找“eval(”即可，当然，还要注意“eval”函数后面可以有空格，tab键之类空白字符。上面的代码片段中，也没考虑到这一点。]]></description>
			<content:encoded><![CDATA[<p>不是闲着蛋疼，也不是批评谁，只是不忍心看到不严谨的代码在网上被疯传，误导初学者。以下引用的代码以及思路来自网络，只针对代码，不针对人。如有雷同，纯属巧合。</p>
<p>来自某大牛python版本的检测服务器上PHP代码中webshell的脚本代码片段如下：</p>
<pre class="brush: python; title: ; notranslate">
findtype=['.php'，'.inc'] #要检查的文件后缀类型
keywords=[ [&quot;eval\(\$\_POST&quot;,&quot;发现PHP一句话木马！&quot;], [&quot;(system|shell_exec|exec|popen)&quot;,&quot;发现PHP命令执行函数!&quot;]]
</pre>
<p>然后，接着是python处理上面列表（数组），把每个列表的第一个元素作为正则表达式内容，然后进行匹配处理的。先看第一个检测“PHP一句话木马”的这个正则。【eval\(\$\_POST】这里转义了字符【_】，字符“_”不是元字符，不需要转义的，其实，转义也无妨，聪明的正则表达式引擎会识别修正的。来说下这个思路的遗漏之处。这里仅仅匹配字符串“eval(”后面的变量“$_POST”，如果是“$_GET”呢？如果是“$_REQUEST”呢？如果程序先把$_POST/$_GET/$REQUEST的key的变量先赋值给一个自定义的变量名，然后在用PHP的“eval”函数执行这个变量呢？是不是就查找不到了？其实，并不需要知道“eval”函数执行的变量名是什么，只要查找“eval(”即可，当然，还要注意“eval”函数后面可以有空格，tab键之类空白字符。上面的代码片段中，也没考虑到这一点。</p>
<div id="attachment_578" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python1.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-578" title="某检测PHP webshell的python脚本考虑欠佳。" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python1-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">某检测PHP webshell的python脚本考虑欠佳。</p></div>
<p>再看看下一个列表的第一个元素。【(system|shell_exec|exec|popen)】，这个正则的意思是只要字符串里包含<strong>“system”、“shell_exec”、“exec”、“popen”</strong>这四组字符串即判定为危险字符。很明显，这个方法太不严谨。如果程序员写的代码中，包含了这四组字符，即可被判定为危险函数。很不准确，误报率极高。见下图</p>
<div id="attachment_579" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python2.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-579" title="某检测PHP webshell的python脚本考虑欠佳。" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python2-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">某检测PHP webshell的python脚本考虑欠佳。</p></div>
<p><strong>到底什么样的代码是可疑的代码？关键词是什么？</strong></p>
<p>可疑的代码肯定是由可以执行危险操作的函数构成，可以执行危险操作的PHP函数最重要的就是“eval”函数了，对于加密的PHP代码（仅变形字符串，<strong>非zend等方式加密</strong>），肯定要用到“eval”函数，所以，对于不管是用哪种加密方法的代码，肯定要用到“eval”函数。其次就是可以执行系统命令的函数了，比如上面某牛的代码中提到的四个“system”、“shell_exec”、“exec”、“popen”。当然还有其他的，比如passthru等。PHP还支持“·”字符（ESC键下面那个）直接执行系统命令。我们可以把正则写成这样【\b(?P&lt;function&gt;eval|proc_open|popen|shell_exec|exec|passthru|system)\b\s*\(】。</p>
<div id="attachment_580" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python3.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-580" title="检测PHP webshell的python脚本相对较为严谨的匹配" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python3-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">检测PHP webshell的python脚本相对较为严谨的匹配</p></div>
<p><strong>解释一下：</strong></p>
<p>大家都知道【\b\b】用来匹配单词两边的位置的。要保证【\b\b】中间的是单词，即使函数名前面加特殊字符，也一样通过匹配，比如加@来屏蔽错误。后面的【\s*】用来匹配空白字符的，包括空格，tab键，次数为0到无数次。前面的【(?P)】是捕获命名组。用来当作python代码直接引用匹配结果的key。</p>
<p>还有的网友提到了，如果我把代码放到图片拓展名的文件里呢？那你只检测.php，.inc的文件，还是找不到我的呀。嗯，是的，如果恶意代码在gif、jpg、png、aaa等乱七八糟的拓展名文件里，是不能被apache、IIS等web Services解析的，必须通过include/require(_once)来引入。那么，我们只要匹配include/require(_once)后面的文件名是不是常规的“.php”、“.inc”文件。如果不是，则为可疑文件。正则如下【(?P&lt;function&gt;\b(?:include|require)(?:_once)?\b)\s*\(?\s*["'](?P&lt;filename&gt;.*?(?&lt;!\.(?:php|inc)))["']】。</p>
<div id="attachment_581" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python4.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-581" title="检测PHP WEBSHELL的python脚本较为严谨做法" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python4-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">检测PHP WEBSHELL的python脚本较为严谨做法</p></div>
<p><strong>解释一下：</strong></p>
<p>先看【(?P&lt;function&gt;\b(?:include|require)(?:_once)?\b)】，【(?P&lt;name&gt;)】为正则表达式的“命名捕获”，PHP中有同样的用法。也就是说，在这括号内的捕获的数据，会分配到结果数组的key为“name”的value中。再看里面的【\b(?:include|require)(?:_once)?\b】,【\b\b】不解释了，为单词边界位置。里面的【(?:include|require)】匹配字符串“include”、“require”两个单词，其中前面的【(?:)】未不分配组，用于提高效率，可以去掉【?:】变成【(include|require)】。在后面一个【(?:_once)】也是做不分配组的操作，便于<a title="提高正则表达式效率" href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/" target="_blank">提高正则表达式效率</a>。同样，后面的量词是“?”代表这个组可有可无。就满足了“include”、“include_once”、“require”、“require_once”四种情况。有的朋友可能这样写【(include|include_once|require|require_once)】也能实现目的。但是，为了更搞的效率，我们对这个正则做优化，针对部分字符串做分支更改，改成上面那个【\b(?:include|require)(?:_once)?\b】。</p>
<p>再看下面的【\s*\(?\s*["'](?P&lt;filename&gt;.+?(?&lt;!\.(?:php|inc)))["']】中，【\s*】匹配空白字符，包括空格，tab键等。后面的【\(?】，匹配字符“(”，后面的量词“?”表示这半个小酷括号可有可无。防止“incude “123.php””这种没有括号的情况。再后面【["']】匹配双引号，单引号的。最后的也是。再看看这个【(?P&lt;filename&gt;.+?(?&lt;!\.(?:php|inc)))】，其中【(?P&lt;filename&gt;)】上面介绍了，为命名捕获，把结果放到match.group(“filename”)里。【.*?】为任意字符，后面的量词是“忽略优先量词”，也就是平常说的“非贪婪”。这里最少匹配零个，（防止.aa、.htaccess这种没有文件名，只有文件拓展名的文件被引入）。后面的【(?&lt;!\.(?:php|inc))】，这里用到了反向零宽断言（环视）的非操作（只匹配位置，不匹配字符串，跟【^$\b】等一样）。这个表达式是针对这个位置的后面字符起作用的，也就是说后面的【["']】的前面不能是“.php”、“.inc”，这里也就是取了文件名的最后的拓展名。（正则里，可以用【^】对字符取非，但是不能对“字符串组”取非，这里用了零宽断言来实现。）</p>
<p>综上所述，最后，鄙人给出的python代码如下：</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/python
#-*- encoding:UTF-8 -*-
###
## @package
##
## @author      CFC4N   &lt;cfc4nphp@gmail.com&gt;
## @copyright   copyright (c) Www.cnxct.Com
## @Version     $Id: check_php_shell.py 37 2010-07-22 09:56:28Z cfc4n $
###
import os
import sys
import re
import time
def listdir(dirs,liston='0'):
	flog = open(os.getcwd()+&quot;/check_php_shell.log&quot;,&quot;a+&quot;)
	if not os.path.isdir(dirs):
		print &quot;directory %s is not exist&quot;% (dirs)
		return
	lists = os.listdir(dirs)
	for list in lists:
		filepath = os.path.join(dirs,list)
		if os.path.isdir(filepath):
			if liston == '1':
				listdir(filepath,'1')
		elif os.path.isfile(filepath):
			filename = os.path.basename(filepath)
			if re.search(r&quot;\.(?:php|inc|html?)$&quot;, filename, re.IGNORECASE):
				i = 0
				iname = 0
				f = open(filepath)
				while f:
					file_contents = f.readline()
					if not file_contents:
						break
					i += 1
					match = re.search(r'''(?P&lt;function&gt;\b(?:include|require)(?:_once)?\b)\s*\(?\s*[&quot;'](?P&lt;filename&gt;.*?(?&lt;!\.(?:php|inc)))[&quot;']''', file_contents, re.IGNORECASE| re.MULTILINE)
					if match:
						function = match.group(&quot;function&quot;)
						filename = match.group(&quot;filename&quot;)
						if iname == 0:
							info = '\n[%s] :\n'% (filepath)
						else:
							info = ''
						info += '\t|-- [%s] - [%s]  line [%d] \n'% (function,filename,i)
						flog.write(info)
						print info
						iname += 1
					match = re.search(r'\b(?P&lt;function&gt;eval|proc_open|popen|shell_exec|exec|passthru|system)\b\s*\(', file_contents, re.IGNORECASE| re.MULTILINE)
					if match:
						function = match.group(&quot;function&quot;)
						if iname == 0:
							info = '\n[%s] :\n'% (filepath)
						else:
							info = ''
						info += '\t|-- [%s]  line [%d] \n'% (function,i)
						flog.write(info)
						print info
						iname += 1
				f.close()
	flog.close()
if '__main__' == __name__:
	argvnum = len(sys.argv)
	liston = '0'
	if argvnum == 1:
		action = os.path.basename(sys.argv[0])
		print &quot;Command is like:\n	%s D:\wwwroot\ \n	%s D:\wwwroot\ 1	-- recurse subfolders&quot;% (action,action)
		quit()
	elif argvnum == 2:
		path = os.path.realpath(sys.argv[1])
		listdir(path,liston)
	else:
		liston = sys.argv[2]
		path = os.path.realpath(sys.argv[1])
		listdir(path,liston)
	flog = open(os.getcwd()+&quot;/check_php_shell.log&quot;,&quot;a+&quot;)
	ISOTIMEFORMAT='%Y-%m-%d %X'
	now_time = time.strftime(ISOTIMEFORMAT,time.localtime())
	flog.write(&quot;\n----------------------%s checked ---------------------\n&quot;% (now_time))
	flog.close()
## 最新代码在文章结尾的链接里给出了。2010/07/31 更新。
</pre>
<p>仅供参考，欢迎斧正。</p>
<p>下面截图为扫描Discuz7.2的效果图，当然，也有误报。相对网上流传的python脚本，误报更少，更精确了。</p>
<div id="attachment_583" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/jiancejieguo.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-583" title="检测PHP WEBSHELL的python脚本的检测结果" src="http://www.cnxct.com/wp-content/uploads/2010/07/jiancejieguo-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">检测PHP WEBSHELL的python脚本的检测结果</p></div>
<p>问：这个方法完美了吗？可以查找目前已知的所有危险函数文件了吗？<br />
答：不能，如果include等引入的文件没有拓展名，这里就匹配不到了。<br />
问：如何解决？<br />
答：留给你解决，聪明的你，肯定可以搞定。<br />
PS：“`”反引号 执行命令的还没写，暂时没好的办法。容易跟SQL语句中的反引号混淆。不太好匹配。如果光匹配反引号就提示的话，那误报太大了。待定吧。（术业有专攻，请勿因为一处不好的代码，否定一个人的能力。你懂的。再次重申，此文只针对代码，不针对人。其次，鄙人给出的python代码随便复制，随便传播，爱留版权就留版权，不爱留就删了相关字符，也就是您爱干吗干吗。）<br />
我先休息一会，明天再说。（前半句为三国杀曹仁的台词，哈。）</p>
<p>=============================我是万恶的分割线======================================<br />
<a href="http://www.cnxct.com/%E5%A6%82%E4%BD%95%E7%B2%BE%E7%A1%AE%E6%9F%A5%E6%89%BEphp-webshell%E6%9C%A8%E9%A9%AC%EF%BC%9F/">最新代码在这里给出了。</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%85%b3%e4%ba%8e%e7%bd%91%e4%b8%8a%e6%b5%81%e4%bc%a0%e6%9f%a5%e6%89%bephp-webshell%e8%84%9a%e6%9c%ac%e4%b8%ad%ef%bc%8c%e4%b8%8d%e4%b8%a5%e8%b0%a8%e7%9a%84%e4%bb%a3%e7%a0%81/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>snoopy.class.php中_striplink方法的正则分析</title>
		<link>http://www.cnxct.com/snoopy-class-php%e4%b8%ad_striplink%e6%96%b9%e6%b3%95%e7%9a%84%e6%ad%a3%e5%88%99%e5%88%86%e6%9e%90/</link>
		<comments>http://www.cnxct.com/snoopy-class-php%e4%b8%ad_striplink%e6%96%b9%e6%b3%95%e7%9a%84%e6%ad%a3%e5%88%99%e5%88%86%e6%9e%90/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 08:13:42 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[生活]]></category>
		<category><![CDATA[snoopy]]></category>
		<category><![CDATA[显卡]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[老爷机]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=572</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/123.jpg"><img class="alignleft sided inline" title="PHP 正则表达式 条件判断 表达式" src="http://www.cnxct.com/wp-content/uploads/2010/07/123-150x150.jpg" alt="" width="150" height="150" /></a>对于已经习惯8点左右起床上班的我来说，生物钟在早上8点左右，准时醒，有时候想赖床，但也无法再次入睡。起床洗漱，打开电脑，玩了两局web的三国杀，逛逛论坛，觉得饿了，才去煮点面条吃。回来继续，无意中打开PPC，看到一位网友“落叶人生”同学的帖子问一个正则问题，纠结了一下是否解释一下，以便给对方释疑解惑，也加固自己的知识。犹豫半天，觉得还是写下吧。下面正题：

PPC链接http://bbs.phpchina.com/thread-189797-1-1.html

preg_match_all("'<\s*a\s.*?href\s*=\s*([\"\'])?(?(1)(.*?)\\1&#124;([^\s\>]+))[^>]*>?(.*?)</a>'isx",$document,$links);
对于一般的规范链　接能很好的使用，但不知道为什么对href=后面的网址不含引号的情况无法提取成功，哪个朋友帮分析下？谢谢！

其实，我没明白他的意思是想提取链接地址href后面的内容的，还是提取整个标签a中间的所有。

在下面的回帖中，他提到了这个正则来自snoopy.class.php的_striplink方法中的正则，遂到sf.net上下载一份原版到本地。]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/">上周提到老爷机坏</a>了，昨天早上早早的抱去修理，维修工程师更换硬件排除法最后得知，故障出现在显卡，插入显卡，主板灯亮，按开关，没反映，或者CPU风扇抖动一下即停止。卸下显卡，开机正常。这位维修人员的结论是显卡坏了，建议更换显卡。我们有N卡9200，只要320元。我提出把显卡放到别的主机上试试，被拒绝了，好吧，那我也拒绝。最后，对方收我20元检测费。虽然我心里有点不情愿，他只是换了几个零件的简单排除法得出很有可能的结论而已，并没有告诉我准确的病因，是显卡的哪里出问题了？能否维修？他都没有告诉我。尽管这样，我还是给了，也没争论。</p>
<p>主机抱回来之后，自己卸下了显卡。开机，上网，打算到网上买块新的。老的显卡是我07年在学校买的。ATI RADEON X550，在当初，还算比较前卫的硬件。周五还赞扬其能勤奋工作到现在，而结果得知出问题的就是它。工作了3年多，不到四年，还能接收吧。主板换了华硕P5GC-MX/1333 ,作为硬件小白的我，也不知道换什么显卡较好。熟悉硬件的朋友，麻烦留言告诉一下，感谢了。现在打开网页，拉动浏览器滑动条的时候，卡的比较厉害，播放电影更是，像放映幻灯片一样。实在不能接受。遂网上搜了相关信息。价格在500左右。是有点贵了。遂暂时作罢。一整天心情都很低落，或者说，自从老爷机出问题了，心情一直很差。中午窝在家里，洗了洗衣服，趁太阳好，把冬天穿的衣服拿出来晒了晒。又挪动电脑附近的两个大桌子，打扫卫生，清理一番。一直忙到下午3点，头饿的晕忽忽的。匆忙到沙县小吃随便吃了点，下午，看会书，睡了会觉，早上送GF回家，起得太早了，困的厉害。睡醒之后，都7点多了，照照镜子，看看自己蓬松的发型，猥琐的样子，不禁笑了一笑。洗了把脸，到小区的理发店里剪了头发，由于是小区内，专门给老头老太太理发的，所以费用仅5元，在上海，应该没有比这还低了吧。晚上，把显示器接到电视盒上，看了会电视，差不多都是娱乐类的弱智脑残节目，我极为反感觉，又将显示器接回主机箱，开机到当当网上看了一番。因工作需要,要做个代码自动审计化的程序，我的想法是，不仅仅停留在对关键危险函数的正则匹配，而是做到语法分析，识别未初始化的变量、未过滤的富文本字段、SQL注入的方法等。想必，肯定的熟悉《编译原理》以及LEX、YACC之类相关知识，后悔大学没认真听，造成自己基础薄太弱了。当然，我也觉得大学的时候，直接教学生这么底层的知识没有循序渐进的引导学生去深入更好。可以从最简单的网页制作开始，然后，让学生对其感兴趣，再引导到动态，然后，联合数据库，然后效率优化，然后代码执行原理，然后编译原理类似这种步骤引导学生更好。比起现在的方式，可能更让学生感兴趣。（扯远了）东看西看，忙到了12点多才睡。</p>
<p>对于已经习惯8点左右起床上班的我来说，生物钟在早上8点左右，准时醒，有时候想赖床，但也无法再次入睡。起床洗漱，打开电脑，玩了两局web的三国杀，逛逛论坛，觉得饿了，才去煮点面条吃。回来继续，无意中打开PPC，看到一位网友“落叶人生”同学的帖子问一个正则问题，纠结了一下是否解释一下，以便给对方释疑解惑，也加固自己的知识。犹豫半天，觉得还是写下吧。下面正题：</p>
<p>PPC链接<a href="http://bbs.phpchina.com/thread-189797-1-1.html">http://bbs.phpchina.com/thread-189797-1-1.html</a></p>
<blockquote>
<div id="code0">
<ol>
<li>preg_match_all(“&#8216;&lt;\s*a\s.*?href\s*=\s*([\"\'])?(?(1)(.*?)\\1|([^\s\&gt;]+))[^&gt;]*&gt;?(.*?)&lt;/a&gt;&#8217;isx”,$document,$links);</li>
</ol>
<p>对于一般的规范链　接能很好的使用，但不知道为什么对href=后面的网址不含引号的情况无法提取成功，哪个朋友帮分析下？谢谢！</p>
</div>
</blockquote>
<p>其实，我没明白他的意思是想提取链接地址href后面的内容的，还是提取整个标签a中间的所有。</p>
<p>在下面的回帖中，他提到了这个正则来自snoopy.class.php的_striplink方法中的正则，遂到sf.net上下载一份原版到本地。</p>
<p><strong>代码如下</strong></p>
<pre class="brush: php; title: ; notranslate">
	function _striplinks($document)
	{
		preg_match_all(&quot;'&lt;\s*a\s.*?href\s*=\s*			# find &lt;a href=
						([\&quot;\'])?					# find single or double quote
						(?(1) (.*?)\\1 | ([^\s\&gt;]+))		# if quote found, match up to next matching
													# quote, otherwise match up to next space
						'isx&quot;,$document,$links);

		// catenate the non-empty matches from the conditional subpattern

		while(list($key,$val) = each($links[2]))
		{
			if(!empty($val))
				$match[] = $val;
		}

		while(list($key,$val) = each($links[3]))
		{
			if(!empty($val))
				$match[] = $val;
		}

		// return the links
		return $match;
	}
</pre>
<p><strong>先看下修饰符部分</strong>。【isx】，大家都知道【i】是不区分大小写；【s】是点号通配模式，也就是元字符【.】可以匹配换行符。在这里的作用是为了防止链接中出现换行的情况；<br />
【x】宽松排列和注释模式，也就是空白字符不会被当成正则表达式的一部分，#后面的为注释，方便阅读的作用了。顺便说下括号后面的双引号后面的单引号，跟修饰符i前面的单引号，他们只是正则的起始标识，不是正则的一部分。其实，表达式里有单引号了，这里最好使用别的，比如斜杠，或者闭合的大括号等。<br />
<strong> 再看表达式</strong>【&lt;\s*a\s.*?href\s*=\s*】,其后面也注释了，是匹配“&lt;a href=”的，第一个【\s】匹配”&lt;”到”a”之间的空白字符，不过一般都没的吧。都直接写”&lt;a&#8230;&#8230;”。后面的【\s】也是空白字符，不详细解释了。在后面的【.*?】是匹配“&lt;a “到“href=”之间的内容，比如”title=”&#8230;..”、target=”&#8230;.”等。【href=】中没有元字符，就是匹配【href=】.</p>
<p><strong>再后面</strong>【([\"\'])?】这里的单引号，双引号是被PHP语法转义的，真正的表达式是【(["'])?】,匹配单引号和双音号，并且，用小括号分配了组（整个表达式的第一组），后面有【?】量词，意味这可有可无。</p>
<p>再后面很重要了。去掉PHP的转义字符之后【(?(1) (.*?)\1 | ([^\s&gt;]+)】，这是一个正则表达式的高级用法，叫“条件判断”表达式。语法为【(? if then| else)】。这里的if部分为【(1)】也就是前面说的“整个表达式的第一组”的内容，如果为真，则使用表达式【(.*?)\1】来匹配（\1是引用捕获的第一个组的内容），如果【(1)】没匹配到，则使用【([^\s&gt;]+)】来匹配。这样，就可以实现没有引号的情况下，也是可以匹配到了。（正则表达式的条件判断语法，【|else】可以不写，表示不用else部分的表达式）</p>
<p>对于楼主的问题。应该怎么改？我刚刚刷新了帖子，看到楼主的正则是可以匹配的呀。</p>
<p>汗，贴下PHP的代码吧。</p>
<pre class="brush: php; title: ; notranslate">

if (preg_match('%&lt;\s*a\s.*?href\s*=\s*([&quot;\'])?(?(1)(.*?)\1|([^\s&gt;]+))[^&gt;]*&gt;(.*?)&lt;/a&gt;%si', $subject)) {
	# Successful match
} else {
	# Match attempt failed
}
</pre>
<p>文章标题跟内容有很大出入，见谅哈。</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/snoopy-class-php%e4%b8%ad_striplink%e6%96%b9%e6%b3%95%e7%9a%84%e6%ad%a3%e5%88%99%e5%88%86%e6%9e%90/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>周末记事-还是我的老爷机</title>
		<link>http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/</link>
		<comments>http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 10:31:32 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[老爷机]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=566</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/piaochong.jpg"><img class="alignleft sided inline" title="夫君子之行，静以修身，俭以养德，非淡泊无以明志，非宁静无以致远。" src="http://www.cnxct.com/wp-content/uploads/2010/07/piaochong-150x150.jpg" alt="" width="150" height="150" /></a>
06年买的主机箱+飞利浦CRT显示器，07年更换电源风扇，08年上半年分别更换了主板，硬盘，下面年，在内存最低价的时候，99块包快递买了DDR2 667的内存条一根，更新了老内存。09年再次更换了电源风扇，10年由于换地方住，搬家，桌子太靠墙，CRT大屁股显示器放不下，买了优派的22寸液晶显示器，鸟枪换炮了，哈。CRT显示器忍痛割爱以50元的价格卖给了小贩，哎，心痛。接着，鼠标又不灵了，更换了鼠标。从06年坚守到现在的器件只有CPU、主机箱、显卡，光驱、键盘了。昨天晚上，10点半左右，老爷机又突然间罢工了，顿时，我心急如焚呀，心想即将到来的周末，作为宅男，我不能接受。赶紧调试吧。首先，我以为是天气太热，导致CPU温度过高，激活主板自动保护策略，强制关机的。赶紧把CPU风扇拿出来，放到空调边吹了会，装上去之后，开机，还是不行，主板灯亮了，但是CPU风扇不转，而且，电源也没反映，我愕然了，难道电源又坏了不成？好吧，我认输，周末再说吧，睡觉。]]></description>
			<content:encoded><![CDATA[<p><strong>我的老爷机：</strong><br />
06年买的主机箱+飞利浦CRT显示器，07年更换电源风扇，08年上半年分别更换了主板，硬盘，下面年，在内存最低价的时候，99块包快递买了DDR2 667的内存条一根，更新了老内存。09年再次更换了电源风扇，10年由于换地方住，搬家，桌子太靠墙，CRT大屁股显示器放不下，买了优派的22寸液晶显示器，鸟枪换炮了，哈。CRT显示器忍痛割爱以50元的价格卖给了小贩，哎，心痛。接着，鼠标又不灵了，更换了鼠标。从06年坚守到现在的器件只有CPU、主机箱、显卡，光驱、键盘了。</p>
<p>昨天晚上，10点半左右，老爷机又突然间罢工了，顿时，我心急如焚呀，心想即将到来的周末，作为宅男，我不能接受。赶紧调试吧。首先，我以为是天气太热，导致CPU温度过高，激活主板自动保护策略，强制关机的。赶紧把CPU风扇拿出来，放到空调边吹了会，装上去之后，开机，还是不行，主板灯亮了，但是CPU风扇不转，而且，电源也没反映，我愕然了，难道电源又坏了不成？好吧，我认输，周末再说吧，睡觉。</p>
<p><strong>前序：</strong><br />
在老爷机罢工之前，一群内网友求助正则匹配html标签中 table之间的内容，要发现的第一个table之间的内容。字符串大约为</p>
<pre class="brush: xml; title: ; notranslate">
&lt;table class=&quot;t1 t2&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;sssssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;
&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;ss
sssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
</pre>
<p>同学A提供【&lt;table[\s\S]*&lt;/table&gt;】(具体记不清了，大体是这个)</p>
<p>这个正则的匹配结果是不能满足其要求的，很明显，【*】为量词优先，导致贪婪匹配把后面最后一个&lt;/table&gt;之前的字符串全部匹配进去了。</p>
<p>见截图：</p>
<div id="attachment_567" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/1111.jpg" rel="lightbox[566]"><img class="size-thumbnail wp-image-567" title="A同学提供的不严谨的正则表达式" src="http://www.cnxct.com/wp-content/uploads/2010/07/1111-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">A同学提供的不严谨的正则表达式</p></div>
<p>接着，另外以为网友提到，后面加U修饰符。对于这个正则，对于这个要求，加U修饰符能达到目的吗？ 答案是可以的。为什么？这种方式可靠吗？有风险吗？有其他方法吗？</p>
<p>先来解释一下U（大写字母U，非小写，小写的是uincode字符模式）是干吗的？ 是对“匹配优先量词（贪婪）”与“<a href="http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/" target="_blank">忽略优先量词（非贪婪）</a>”的取反，也就是说，原来是【*】、【+】的，会按照【*?】、【+?】来执行，如果是【*?】、【+?】的，则按照【*】、【+】来执行，这个修饰符很怪，很乱，如果正则为【\w+】,为了达到“非贪婪匹配”，使用了修饰符U。过几天，你修改了这个正则，修改为【\w+\s+?】,你的本意是在原来的基础上，加上非贪婪的空白字符的匹配，可是，后面的大写字母U修饰符也对你前面的非贪婪取反了，从而，导致匹配错误，所以，建议大家不要使用大写字母的U修饰符，直接在表达式里写好贪婪还是非贪婪。</p>
<p>我的答案是【&lt;table[^&gt;]+?&gt;(?&gt;((?!&lt;/table&gt;).(?&lt;!&lt;table))+)&lt;/table&gt;】。</p>
<p>我靠，你这这什么玩意？这么乱？这是什么意思？</p>
<p><strong>解释一下：</strong></p>
<ol>
<li>【&lt;table[^&gt;]+?&gt;】部分是匹配“&lt;table class=”t1 t2&#8243;&gt;”这种table的开头，包括属性的字符串，其中，使用了忽略优先量词（非贪婪），由于其属性不会太多，常规下不超过50个字符串，所以，没有使用固化分组，或者<a title="PHP 正则表达式 占有优先量词" href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/" target="_blank">占有优先量词</a>来减少回溯。</li>
<li>【&lt;/table&gt;】(最后面的)是匹配字符串结束的。不用解释了吧。</li>
<li>【(?&gt;((?!&lt;/table&gt;).(?&lt;!&lt;table))+)】这个比较长，主要是匹配&lt;table&#8230;.到&lt;/table&gt;中间的字符串，其中最外面一层【(?&gt;)】是<a title="PHP 正则表达式 占有优先量词" href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/" target="_blank">占有优先量词</a>，用来防止不必要的回溯，防止中间超长的字符串造成崩溃。【(?!&lt;/table&gt;)】是顺序零宽断言非操作，匹配位置，针对其后面的规则【.】，意思就是说，规则【.】后面不能是字符串“&lt;/table&gt;”，同样正则【(?&lt;!&lt;table】是逆序零宽断言非操作，也匹配位置，针对其前面的规则【.】，意思就是说，规则【.】前面不能是字符串“&lt;table&#8230;”，这样，两个零宽断言来确定一个字符串，如果是多个字符串，则加上匹配优先量词【+】，但是这个【+】的位置要注意了，不能直接放在【.】的后面，因为要保证每个【.】匹配的字符串，前后的规则都符合两个零宽断言，则需要放在外面，也就是上面所写的那样。</li>
</ol>
<p>OK，解释完毕，你明白了没？如果没，那是我的错。请留言，批评，我承认错误。（当使用匹配的时候，为了更准确，建议开启不区分大小写模式，以及，多行匹配模式，即修饰符i和修饰符s，小写的s，不是大写的，大写的S是另外的含义&lt;以后写&gt;。）</p>
<p>见截图：</p>
<div id="attachment_569" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/222.jpg" rel="lightbox[566]"><img class="size-thumbnail wp-image-569" title="相对比较严谨，比较准确的正则表达式" src="http://www.cnxct.com/wp-content/uploads/2010/07/222-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">相对比较严谨，比较准确的正则表达式</p></div>
<p>测试代码：</p>
<pre class="brush: php; title: ; notranslate">
$str='111&lt;table class=&quot;t1 t2&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;sssssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;
&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;ss
sssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;ssss';
preg_match_all('%&lt;table[^&gt;]+?&gt;(?&gt;((?!&lt;/table&gt;).(?&lt;!&lt;table))+)&lt;/table&gt;%si', $str, $result, PREG_PATTERN_ORDER);
print_r($result[0]);
</pre>
<p>我的答案可以解决问题吗？可以。准确吗？还行，不太准。为什么？如果table中间有嵌套，则无法正确匹配。如何修复？正则递归匹配。如果递归？</p>
<p>留给你研究吧。<a href="http://www.cnxct.com/cfc4n%E5%B0%8F%E8%AF%95%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/" target="_blank">CFC4N小试正则表达式</a>里已经介绍了一个关于递归匹配的例子，你可以参考一下。</p>
<p><strong>后续：</strong></p>
<p>老爷机挂了，我一夜没睡着，早上6点10分就醒了，起来之后，捣鼓两下，也没心情了，已经知道大体的症状。手头没工具，也没法测试，算了，索性洗漱去公司。走的早也好，地铁上没多少人，一路不拥挤，唯一的缺点就是没拿到“时代报”。不过到了公司楼下，有派发的，顺手拿了一份。到座位上，心思还在我心爱的老爷机上，也有重新买台新机器的想法，到DELL官方网站上搜了几下，发现价格奇贵，光主机，都4K-5K，看了一会，我就大小这个念头了，作为寄生在这大城市的P民，也别要求太高了。讲究用吧。哎，打算周末冒热抱出去找维修铺，各位，祝福我吧。</p>
<p>PS：下午，拿了早上没看的报纸去厕所，心想，这次终于不干等了，可以打发时间了。当我到厕所里的时候，我震惊了，我靠，马桶上起码5份报纸，而且，还都不一样。汗。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PHP中正则表达式对UNICODE字符码的匹配</title>
		<link>http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/</link>
		<comments>http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 16:47:27 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[ascii]]></category>
		<category><![CDATA[PCRE]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/lily_of_the_valley.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/lily_of_the_valley-150x150.jpg" alt="" title="PHP正则表达式匹配UNICODE字符" width="150" height="150" class="alignleft sided inline" /></a>
我们在来分析一下这个网友写的正则表达式【[chr(128)-chr(256)]+】，正则表达式的PCRE引擎是如何解释这个正则的呢？首先，我们要知道，在正则表达式中，中括号【[]】表示字符组，字符组中除了连接符【-】只外，都不是元字符，也就是说，都是普通字符，当然，如果连字符出现在第一个，或者不是标识两个字符之间范围的，都是普通的字符横杠“-”罢了。这里的chr(128)只是标识ASCII码为128（确切的说，ASCII码只是0-127个，128到其他的，应该不叫ASCII码了。），但是在正则里，他仍然代表【c、h、r、(、1、2、8、)】（顿号不是，只是区分易读的）这八个字符罢了。这个正则里的连接字符，是哪些范围呢？很明显，这里的连接字符的范围是【)-c】，“)”ASCII码为0x29，也就是十进制的41；“c”的ASCII码为0x63，也就是十进制的99，那么，他这个连接字符的范围就是ASCII 41（chr(41)）到ASCII 99（chr(99)）之间的字符。]]></description>
			<content:encoded><![CDATA[<p>酷暑难耐，又在家宅一整天。天气热或许是借口，尽管不热，我也喜欢宅在家。晚上看新三国83集（插一句，最近世界杯很火，可是我不看世界杯。来鄙视我吧），一直看到10点半，突然觉得肚子痛，赶紧直奔厕所。如厕之后，觉得精神抖擞，容光焕发，年轻了二十多岁，打开QQ，看到N多条消息，其中有条是生命如蓝同学留的。打开一看，是PPC的链接，突然觉得我好久没登陆PPC了，想当年&#8230;&#8230;..算了，看链接吧。</p>
<p> 打开链接，看到标题是“请教PHP 一个正则匹配的问题”，又是正则表达式，好吧，看下，谁让俺比较喜欢鼓捣正则呢。下面开始正题。<br />
网友ainiaa的问题是</p>
<blockquote><p>
PHP代码如下</p>
<pre class="brush: php; title: ; notranslate">
$words = &quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSRUVWXYZ!@#$%^&amp;*()_+-=[]\\,./{}|&lt;&gt;?'\&quot;你好啊我们&quot;;
$otherStr=preg_replace(&quot;/[chr(128)-chr(256)]+/is&quot;,&quot; &quot;,$words);
echo 'otherStr:',$otherStr;
</pre>
<p>为什么打印的结果会是：<br />
otherStr: ! #$% &#038; {}| &#8216;”你好啊我们</p>
<p>麻烦问下其中正则表达式 /[chr(128)-chr(256)]+/is 代表什么意思？<br />
如果/[chr(128)-chr(256)]+/is 指的是ascii码在128到256的字符，为什么a-zA-Z这样的字符也被替换掉了，他们的ascii码是小于127的。<br />
最令人郁闷的是为什么ascii码同在0-127区间”#”,”$”,”%”,”&#038;”, “!”,” {“,”}”,”|”,” &#8216;”,”确没有被替换掉？？？？<br />
更令人感觉神奇的是 如果把正则表达式修改为”/[chr(128)-chr(256)]+/s”的话，输出的结果就变成了：  otherStr:  defg ijklmnopq stuvwxyz ! #$% &#038; {}| &#8216;”你好啊我们<br />
只是把正则表达式中的符号‘i’给去掉，结果缺失这样的。 完全的令我理解不了。<br />
不知各位 有何见解？？？？<br />
另附ascii 码 对照表<br />
（这个ASCII码表的图我就不贴了）
</p></blockquote>
<p>回帖中，有个网友说没解析chr(128)这些，并给出了新的解决方法。首先说下此网友回答的是正确的，先不评论他是否“知其然，且知其所以然”，这位网友没有给出错误的原因。</p>
<p><strong>CFC4N来回答一下这位网友：</strong></p>
<p>PHP的正则的preg_match函数用的是PCRE正则引擎，这位网友的代码中，PCRE引擎处理的正则表达式为【/[chr(128)-chr(256)]+/is】，后面的is是什么呢？<br />
在PHP的正则里，边界字符后面的叫模式修饰符。它会告诉引擎如何解析，处理正则。其中i修饰符表示不区分大小写。s表示“点号通配模式”，用来让正则里的元字符点号【.】可以匹配换行符，这个修饰符仅对点号【.】起作用。在这位网友的问题中，修饰符s并不起作用的。</p>
<p><strong>查找原因：</strong><br />
我们在来分析一下这个网友写的正则表达式【[chr(128)-chr(256)]+】，正则表达式的PCRE引擎是如何解释这个正则的呢？首先，我们要知道，在正则表达式中，中括号【[]】表示字符组，字符组中除了连接符【-】只外，都不是元字符，也就是说，都是普通字符，当然，如果连字符出现在第一个，或者不是标识两个字符之间范围的，都是普通的字符横杠“-”罢了。这里的chr(128)只是标识ASCII码为128（确切的说，ASCII码只是0-127个，128到其他的，应该不叫ASCII码了。），但是在正则里，他仍然代表【c、h、r、(、1、2、8、)】（顿号不是，只是区分易读的）这八个字符罢了。这个正则里的连接字符，是哪些范围呢？很明显，这里的连接字符的范围是【)-c】，“)”ASCII码为0&#215;29，也就是十进制的41；“c”的ASCII码为0&#215;63，也就是十进制的99，那么，他这个连接字符的范围就是ASCII 41（chr(41)）到ASCII 99（chr(99)）之间的字符。也就是说，这位网友的正则的范围是【[hr)-c(]】，就是chr(41)到chr(99)外加hr这两个字母和前面的“(”。<br />
网友第一次测试的时候，有修饰符i，意思就是说，不区分大小写，那么在chr(41)到chr(99)之间的字符，以及这些字符如果有大小写，则包括他们的大小写都符合匹配。都会被替换成空。其第二次测试的时候，去掉了修饰符i，进行了不区分大小写的匹配，由于其范围只到c，但突然，再除了小写字母的“h”、“r”，所以，测试结果会多出“defgijklmnopqstuvwxyz”。所以，他的结果出现了这些差别。<br />
<div id="attachment_544" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/reg1.jpg" rel="lightbox[543]"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/reg1-150x150.jpg" alt="" title="PHP正则表达式匹配UNICODE字符" width="150" height="150" class="size-thumbnail wp-image-544" /></a><p class="wp-caption-text">PHP正则表达式匹配UNICODE字符</p></div><br />
网友的表达式等同于如下图所示<br />
<div id="attachment_545" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/reg2.jpg" rel="lightbox[543]"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/reg2-150x150.jpg" alt="" title="PHP正则表达式匹配UNICODE字符" width="150" height="150" class="size-thumbnail wp-image-545" /></a><p class="wp-caption-text">PHP正则表达式匹配UNICODE字符</p></div></p>
<p><strong>解决办法：</strong><br />
错误的原因找出来了，那么，解决的办法呢？<br />
我们先来看看这位网友的需求，他的需求是将unicode（ASCII只是0-127位的，128之后的，应该叫UNICODE码）的chr(128)到chr(255)之间的字符匹配，替换为空罢了。正则表达式里，对十六进制的字符匹配的表示方式有两种，【\u】和【\x{}】，前者只能表示【\u】后面4位的十六进制数值，而后者【\x{}】则可以表示任意多的十六进制位数（写在大括号中）。<br />
那么，这个正则表达式该如何写？？？？</p>
<p>网友的目的是chr(128)到chr(255)，那么就是【[\u0080-\u00FF]】或者【[\x{0080}-\x{00FF}]】。<br />
其目的是匹配下图中的红框内字符<br />
<div id="attachment_546" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/mudi.jpg" rel="lightbox[543]"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/mudi-150x150.jpg" alt="" title="UNICODE字符128到255字符集图" width="150" height="150" class="size-thumbnail wp-image-546" /></a><p class="wp-caption-text">UNICODE字符128到255字符集图</p></div><br />
提醒一下，PHP里正则匹配unicode字符时，需要使用u修饰符。<br />
根据网友需求，更改正则之后的PHP代码如下：</p>
<pre class="brush: php; title: ; notranslate">
$words = &quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSRUVWXYZ!@#$%^&amp;*()_+-=[]\\,./{}|&lt;&gt;?'\&quot;你好啊我们&quot;;
$otherStr=preg_replace(&quot;//[\x{0080}-\x{00FF}]+/iu&quot;,&quot; &quot;,$words);
echo 'otherStr:',$otherStr;
</pre>
<p>其运行结果是仍然输出那段字符串，为什么呢？因为哪些字符串都不在chr(128)到chr(255)的范围之内。<br />
（测试时，注意文件编码为UTF-8）<br />
以上为鄙人愚见，欢迎批评指正。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PHP正则表达式的效率：回溯与固化分组</title>
		<link>http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/</link>
		<comments>http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 07:39:52 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[回溯]]></category>
		<category><![CDATA[固化分组]]></category>
		<category><![CDATA[效率]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[环视]]></category>
		<category><![CDATA[贪婪]]></category>
		<category><![CDATA[零宽断言]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/06/hua.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/hua-150x150.jpg" alt="" title="PHP正则表达式的回溯与固化分组" width="150" height="150" class="alignleft sided inline" /></a>上文中，我们聊到了一点关于PHP中（NFA PCRE）正则表达式匹配优先量词，忽略优先量词的匹配原理了。那么上文留下的问题，您的答案是什么呢？
对于第一种贪婪匹配的匹配规则，回溯的9次是正则【</script>】对字符串“</script>”匹配时，构成的回溯，回溯的次数，恰好是字符串的长度。
第二种非攀谈匹配规则，回溯5次，是正则【.+?】对字符串“123456”匹配时构成的回溯。回溯的次数，为字符串长度减去最小次数。也就是6-1=5次。如果正则表达式为【.*?】那么，回溯次数就是6次了。
第三种正则是零宽断言，或者叫环视。（暂且不说。）
]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_498" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/hua.jpg" rel="lightbox[491]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/hua-150x150.jpg" alt="" title="PHP正则表达式的回溯与固化分组" width="150" height="150" class="size-thumbnail wp-image-498" /></a><p class="wp-caption-text">PHP正则表达式的回溯与固化分组</p></div><br />
上文中，我们聊到了一点关于PHP中（NFA PCRE）正则表达式匹配优先量词，忽略优先量词的匹配原理了。那么上文留下的问题，您的答案是什么呢？<br />
先来看下问题。</p>
<blockquote><p>
字符串</p>
<pre class="brush: php; title: ; notranslate">
$str = '&lt;script&gt;123456&lt;/script&gt;';
</pre>
<p>正则表达式为</p>
<pre class="brush: php; title: ; notranslate">
$strRegex1 = '%&lt;script&gt;.+&lt;\/script&gt;%';
$strRegex2 = '%&lt;script&gt;.+?&lt;\/script&gt;%';
$strRegex3 = '%&lt;script&gt;(?:(?!&lt;\/script&gt;).)+&lt;\/script&gt;%';
</pre>
<p>这三个正则，分别会造成几次回溯呢？？
</p></blockquote>
<p>答案：</p>
<pre class="brush: php; title: ; notranslate">
$strRegex1 = '%&lt;script&gt;.+&lt;\/script&gt;%';    //9次，记得区别转义符号。
$strRegex2 = '%&lt;script&gt;.+?&lt;\/script&gt;%';  //5次
$strRegex3 = '%&lt;script&gt;(?:(?!&lt;\/script&gt;).)+&lt;\/script&gt;%';  //7次
</pre>
<p>对于第一种贪婪匹配的匹配规则，回溯的9次是正则【</script>】对字符串“</script>”匹配时，构成的回溯，回溯的次数，恰好是字符串的长度。<br />
第二种非贪婪匹配规则，回溯5次，是正则【.+?】对字符串“123456”匹配时构成的回溯。回溯的次数，为字符串长度减去最小次数。也就是6-1=5次。如果正则表达式为【.*?】那么，回溯次数就是6次了。<br />
第三种正则是零宽断言，或者叫环视。（暂且不说。）<br />
在NFA正则引擎中，回溯是他的灵魂，所以，不管是贪婪，非贪婪，环视等写法中肯定会有回溯的出现的，这个我们无法避免（用词不太准确），但是，我们可以减少回溯的次数，或者保护其中一部分匹配的规则不进行回溯。</p>
<p>对于<a href="http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/">上篇BLOG</a>上提到的鸟哥谈到一个非贪婪引起的大量回溯问题，大家可以知道，回溯，确实是浪费资源的罪魁祸首，那么，我们能否不让其回溯呢？<br />
答案是肯定的，NFA引擎中，有个概念，叫固化分组。引用一下书上的概念</p>
<blockquote><p>
具体来说，使用「(?>…)」的匹配与正常的匹配并无差别，但是如果匹配进行到此结构之后（也就是，进行到闭括号之后），那么此结构体中的所有备用状态都会被放弃。也就是说，在固化分组匹配结束时，它已经匹配的文本已经固化为一个单元，只能作为整体而保留或放弃。括号内的子表达式中未尝试过的备用状态都不复存在了，所以回溯永远也不能选择其中的状态（至少是，当此结构匹配完成时，“锁定（locked in）”在其中的状态）。
</p></blockquote>
<p>那么，固化分组到底有什么用处呢？我们来举个例子。（找不到合适的例子，俺只好借用一下书上的例子了）<br />
比如要处理一批数据，原来格式为123.456，后来因为浮点数显示问题，部分数据格式变为123.456000000789这种，，要求做到只保留小数点后面2-3位，但是，最后一位不能为0，这个正则如何写呢？（下面直接考虑小数点后面的数字），写出正则之后，我们还要用这个正则去匹配数据，把原来的数据替换成匹配的结果。<br />
首先，我们可以立刻写出这样的正则【\.\d\d[1-9]?\d*】，PHP代码为</p>
<pre class="brush: php; title: ; notranslate">
$str = preg_replace('\.(\d\d[1-9]?)\d*','\\1',$str);  //匹配结果的group1进行反向引用
</pre>
<p>很明显，这种写法，对于部分数据格式为123.456的这种格式，白白的处理了一遍，为了提高效率，我们还要对这个正则进行处理。从123.456这个字符串跟其他的比较一下，我们发现，是疑问123.456这个数据后面没数字了，所以，白白处理一遍。那好办，我们对这个正则改造一下，把后面的量词*改成+，这样对于123.45 小数点后面1，2位数字的，不会去白白处理，而且，对三位以上数字的，处理正常。其PHP代码为</p>
<pre class="brush: php; title: ; notranslate">
$str = preg_replace('\.(\d\d[1-9]?)\d+','\\1',$str);
</pre>
<p>好了，这个正则真的没问题吗？？确定吗？上篇博文，我们了解了匹配原理，那么，我们也分析一下这个正则的匹配过程吧。<br />
字符串"123.456",正则表达式为【\.(\d\d[1-9]?)\d+】，我们来看下<br />
首先（小数点前123不说了），【\.】匹配"."，匹配成功，把控制权给下一个【\d】，【\d】匹配“4”成功，把控制权给第二个【\d】，这个【\d】匹配“5”成功，然后，把控制权给了【[1-9]?】，由于量词是【?】，正则表达式遵循“量词优先匹配”，而且，此处是【?】，还会留下一个回溯点。然后匹配"6"成功，然后把控制权给【\d+】，【\d+】发现后面没字符了，最遵循“后进先出”规则，回到上一个回溯点，进行匹配，这时，【[1-9]?】会交还出其匹配的字符“6”，【[1-9]?】匹配“6”成功。匹配完成了。大家发现【(\d\d[1-9]?)】匹配的结果确是"45",并不是我们想要的“456”，“6”被【\d+】匹配去了。那么，我们该如何办呢？ 能否让【[1-9]?】匹配一旦成功，不进行回溯呢？这就用到了我们上面说的"固化分组", PHP（preg_replace函数）中使用的正则引擎支持固化分组，我们根据固化分组的写法，可以把代码改成如下方式</p>
<pre class="brush: php; title: ; notranslate">
$str = preg_replace('\.(\d\d(?&gt;[1-9]?))\d+','\\1',$str);
</pre>
<p>改成这样的话，那字符串“123.456“是不符合要求，不会被匹配的。那我们就可以实现我们的要求了。</p>
<p>从上面的例子中，知道了固化分组的作用，那么对于鸟哥BLOG上写的那个非贪婪的回溯问题，我们能否也对其改造，使得其不回溯呢？<br />
先看下鸟哥给的答案</p>
<blockquote>
<pre class="brush: plain; title: ; notranslate">/&lt;script&gt;[^&lt;]*&lt;\/script&gt;/is
</pre>
</blockquote>
<p>鸟哥写的很精悍。排除“<”之外的所有字符都符合，而且，中间部分不回溯，效率高。可是，如果中间有字符“<“的话（如下代码）</p>
<pre class="brush: plain; title: ; notranslate">
&lt;script&gt;
if a &lt; b
&lt;/script&gt;
</pre>
<p>那鸟哥的这个正则就不能匹配，就不能实现我们想要的功能了。<br />
那我们可以根据 固化分组、环视(零宽断言)来实现这个要求，最后，CFC4N给出的正则以及PHP代码事例如下</p>
<pre class="brush: php; title: ; notranslate">
$reg = '%&lt;script&gt;(?&gt;[^&lt;]*)(?&gt;(?!&lt;/?script&gt;)&lt;[^&lt;]*)*&lt;/script&gt;%is';
$str = str_pad(&quot;&lt;script&gt;&quot;, 111111, &quot;*&quot;);    //字符长度大于PHP回溯限制的100000
$str .= 'if a &lt; b ; if b &gt; c;&lt;/script&gt;';    //随便加几个包含 &lt; &gt; 的测试字符
$ret = preg_replace($reg, &quot;OK&quot;, $str);
print_r($ret);                              //打印结果 OK，证明匹配正确
var_dump(preg_last_error());                //上一次匹配错误。其输出为 int(0)
</pre>
<p>嗨，同学，你看明白了吗？</p>
<p>以上为小菜CFC4N的愚文，如有错误，欢迎指出。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>小议正则表达式效率：贪婪、非贪婪与回溯</title>
		<link>http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/</link>
		<comments>http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/#comments</comments>
		<pubDate>Fri, 18 Jun 2010 09:48:08 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[回溯]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[贪婪]]></category>
		<category><![CDATA[非贪婪]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/06/tanlan.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/tanlan-150x150.jpg" alt="" title="贪婪还是非贪婪？" width="150" height="150" class="alignleft sided inline" /></a> 前几天看了鸟哥的BLOG上写的关于正则表达式的回溯与递归的限制时，对贪婪、非贪婪产生的回溯有疑问，遂近段时间，仔细的学习研究了一下，现在把经验心得与大家分享一下。
先扫盲一下什么是正则表达式的贪婪，什么是非贪婪？或者说什么是匹配优先量词，什么是忽略优先量词？
好吧，我也不知道概念是什么，来举个例子吧。]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cnxct.com/wp-content/uploads/2010/06/tanlan.jpg" rel="lightbox[481]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/tanlan-150x150.jpg" alt="" title="贪婪还是非贪婪？" width="150" height="150" class="alignleft sided inline" /></a> 前几天看了<a href="http://www.laruence.com/2010/06/08/1579.html">鸟哥的BLOG</a>上写的关于正则表达式的回溯与递归的限制时，对贪婪、非贪婪产生的回溯有疑问，遂近段时间，仔细的学习研究了一下，现在把经验心得与大家分享一下。<br />
（我日，这里好像被左侧的图挡着了，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数，换行换行凑字数）<br />
先扫盲一下什么是正则表达式的贪婪，什么是非贪婪？或者说什么是匹配优先量词，什么是忽略优先量词？<br />
好吧，我也不知道概念是什么，来举个例子吧。<br />
某同学想过滤<script>....</script>之间的内容，那是这么写正则以及程序的。</p>
<pre class="brush: php; title: ; notranslate">
$str = preg_replace('%&lt;script&gt;.+?&lt;/script&gt;%i','',$str);//非贪婪
</pre>
<p>看起来，好像没什么问题，其实则不然。若</p>
<pre class="brush: php; title: ; notranslate">
$str = '&lt;script&lt;script&gt;alert(document.cookie)&lt;/script&gt;&gt;alert(document.cookie)&lt;/script&gt;';
</pre>
<p>那么经过上面的程序处理，其结果为</p>
<pre class="brush: php; title: ; notranslate">
$str = '&lt;script&lt;script&gt;alert(document.cookie)&lt;/script&gt;&gt;alert(document.cookie)&lt;/script&gt;';
$str = preg_replace('%&lt;script&gt;.+?&lt;/script&gt;%i','',$str);//非贪婪
print_r($str);
//$str 输出为 &lt;script&gt;alert(document.cookie)&lt;/script&gt;
</pre>
<p>仍然达不到他想要的效果。上面的就是非贪婪，也有的叫惰性。其标志非贪婪的标识为量数元字符后面加? ，比如 +?、*?、??(比较特殊，以后的BLOG中，我会写到)等。即标识非贪婪，如果不写?就是贪婪。比如</p>
<pre class="brush: php; title: ; notranslate">
$str = '&lt;script&lt;script&gt;alert(document.cookie)&lt;/script&gt;&gt;alert(document.cookie)&lt;/script&gt;';
$str = preg_replace('%&lt;script&gt;.+&lt;/script&gt;%i','',$str);//非贪婪
print_r($str);
//$str 输出为 &lt;script 只有这些了，好像还是不太合适，哈，您知道如何重写那个正则吗？
</pre>
<p>以上为贪婪，非贪婪的区别介绍。下面，聊下贪婪、非贪婪引起的回溯问题。先看个小例子。<br />
正则表达式为<strong>\w*(\d+)</strong>，字符串为cfc456n，那么，这个正则匹配的$1是多少？？</p>
<p>如果您回答是 456,那么，恭喜你，回答<strong>错</strong>了，其结果不是456，而是6，您知道为什么吗？</p>
<p>CFC4N来解释一下，当正则引擎用正则<strong>\w*(\d+)</strong>去匹配字符串cfc456n时，会先用\w*去匹配字符串cfc456n，首先，\w*会匹配字符串cfc456n的所有字符，然后再交给\d+去匹配剩下的字符串，而剩下的没了，这时，\w*规则会不情愿的吐出一个字符，给\d+去匹配，同时，在吐出字符之前，记录一个点，这个点，就是用于<strong>回溯</strong>的点，然后\d+去匹配n，发现并不能匹配成功，会再次要求\w*再吐出一个字符，\w*会先再次记录一个回溯的点，再吐出一个字符。这时，\w* 匹配的结果只有cfc45了，已经吐出6n了，\d+再去匹配6，发现匹配成功，则会通知引擎，匹配成功了，就直接显示出来了。所以，(\d+)的结果是6，而不是456。</p>
<p>当上面的正则表达式改为 <strong>\w*?(\d+)</strong>（注意，此处为非贪婪），字符串仍然为cfc456n，那么，这时候，正则匹配的$1是多少？？<br />
甲同学回答：结果是 456。<br />
嗯，是的，正确，是456，CFC4N弱弱的问下，为什么是456 呢？<br />
我在来解释一下 为什么是456<br />
正则表达式有条规则，是量词优先匹配，所以\w*?会先去匹配字符串cfc456，由于\w*?是非贪婪，正则引擎会用表达式\w+?每次仅匹配一个字符串,然后再将控制权交给后面的\d+去匹配下一个字符，同时，记录一个点，用于在匹配不成功的时候，返回这里，再次匹配，也就是回溯点。由于\w后面是量词是*，*表示0到无数次，所以，首先是0次，也就是\w*?匹配个空，记录回溯点，将控制权交给\d+,\d+去匹配cfc456n的第一个字符c,然后，匹配失败，于是乎，接着讲控制权交给\w*?去匹配cfc456n的c，\w*?匹配c成功，由于是非贪婪，所以，他每次只匹配一个字符，记录回溯点，然后再将控制权交给\d+匹配f,接着，\d+匹配f再失败，再把控制权给\w*?，\w*?再匹配c,记录回溯点（这时\w*?匹配结果是cfc了），再把控制权给\d+，\d+去匹配4，匹配成功，然后，由于量词是+，就是1到无数次，所以，接着往后匹配，再匹配5，成功，再接着，再匹配6，成功，再接着，继续匹配操作，下一个字符是n，匹配失败，这时，\d+会吧控制权交出去。由于\d+后面已经没有正则表达式了，所以，整个正则表达式宣告匹配完成，其结果就是 cfc456, 其中第一组结果是456。亲爱的同学，您明白刚刚的题目的结果，为什么是456了吗？</p>
<p>好了，您是否从上面的例子了解了贪婪，非贪婪的匹配原理了？那您是否明白您在什么时候需要使用贪婪，非贪婪去处理您的字符串了？<br />
鸟哥的文章里讲到针对<br />
表达式、程序为</p>
<pre class="brush: php; title: ; notranslate">
$reg = &quot;/&lt;script&gt;.*?&lt;\/script&gt;/is&quot;;
$str = &quot;&lt;script&gt;********&lt;/script&gt;&quot;; //长度大于100014
$ret = preg_repalce($reg, &quot;&quot;, $str); //返回NULL
</pre>
<p>其原因就是回溯太多了，直到造成耗尽栈空间爆栈。</p>
<p>再来看个例子。<br />
字符串</p>
<pre class="brush: php; title: ; notranslate">
$str = '&lt;script&gt;123456&lt;/script&gt;';
</pre>
<p>正则表达式为</p>
<pre class="brush: php; title: ; notranslate">
$strRegex1 = '%&lt;script&gt;.+&lt;\/script&gt;%';
$strRegex2 = '%&lt;script&gt;.+?&lt;\/script&gt;%';
$strRegex3 = '%&lt;script&gt;(?:(?!&lt;\/script&gt;).)+&lt;\/script&gt;%';
</pre>
<p>这三个正则，分别会造成几次回溯呢？？</p>
<p>答案见下篇 <a href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/">PHP正则表达式的效率：回溯与固化分组</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>端午节之后一周总结</title>
		<link>http://www.cnxct.com/%e7%ab%af%e5%8d%88%e8%8a%82%e4%b9%8b%e5%90%8e%e4%b8%80%e5%91%a8%e6%80%bb%e7%bb%93/</link>
		<comments>http://www.cnxct.com/%e7%ab%af%e5%8d%88%e8%8a%82%e4%b9%8b%e5%90%8e%e4%b8%80%e5%91%a8%e6%80%bb%e7%bb%93/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 02:31:13 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[瞎扯淡]]></category>
		<category><![CDATA[端午节]]></category>
		<category><![CDATA[精通正则表达式]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/%e7%ab%af%e5%8d%88%e8%8a%82%e4%b9%8b%e5%90%8e%e4%b8%80%e5%91%a8%e6%80%bb%e7%bb%93/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/06/xiachedan.gif"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/xiachedan-150x150.gif" alt="" title="瞎扯淡" width="150" height="150" class="alignleft sided inline" /></a>
在当当网上买了本书《精通正则表达式》，送货速度很快，前天晚上下的订单，第二天中午就送到了。值得表扬。姐姐来我这玩，带来了一点粽子，蜜枣馅的，还有煎饼等家乡的特产，非常感谢。陪小外甥再次看了《汽车总动员》，！@#￥#%%￥……￥&#038;%……*……]]></description>
			<content:encoded><![CDATA[<p>本周主题：瞎扯淡。<br />
<div id="attachment_470" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/xiachedan.gif" rel="lightbox[471]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/xiachedan-150x150.gif" alt="" title="瞎扯淡" width="150" height="150" class="size-thumbnail wp-image-470" /></a><p class="wp-caption-text">CFC4N 端午节之后一周总结</p></div></p>
<p>记下本周（确切的说，是上周）流水账：</p>
<ul>
<li>在当当网上买了本书《精通正则表达式》，送货速度很快，前天晚上下的订单，第二天中午就送到了。值得表扬。</li>
<li>姐姐来我这玩，带来了一点粽子，蜜枣馅的，还有煎饼等家乡的特产，非常感谢。</li>
<li>陪小外甥再次看了《汽车总动员》，！@#￥#%%￥……￥&#038;%……*……</li>
<li>CNXCT.COM域名已经到期，忘记续费了，还好，GLEON同学没忘记，悄悄的续费了。</li>
<li>端午在家看了新买的书《精通正则表达式》，直接从第四章匹配原理开始看，因为我买书的主要原因是想知道匹配原理。还有就是仔细的看了在非贪婪、贪婪的情况下，匹配时候的回溯详情，匹配的优先顺序，回溯的次数，效率等情况。致力做到不光写得出正则，还要写的出高效率的正则表达式</li>
<li>最近比较懒，从过年回来，基本没运动过，上上上周，打了羽毛球。总共运动时间大约20分钟，其中，大部分时间是捡球，羽毛球老是被我抽到树枝上。想办法把羽毛球取下来，也是件麻烦事。周围没有很长的竹竿，树枝之类东西，只好从地上捡起石块砸。结果，右手胳膊酸了一周。昨天，跟几个朋友一起打升级。由于右手一直轻轻的拿鼠标，没有那么用力的捏牌，结果，今天胳膊又酸了。CFC4N想弱弱的问，难道打升级也算运动？</li>
<li>昨天，把床上铺的床单取掉了，直接躺在竹席上，结果，夜里肚子被冰的很痛，一夜没睡好，结果，现在精神状态很差。</li>
<li>今天看到还算是比较轰动的IT新闻，<a href="http://tech.qq.com/a/20100617/000083.htm/">马化腾马云收编草根网站 互联网大佬争夺站长</a>，新闻的主要内容是腾讯收购草根的IT公司康盛创想，其主打产品是Discuz！，不知道是真还是假。很多网友都调侃说到“期待使用’QQ PassPort‘登陆各大BBS”，我稍微想了一下，如果实现，应该也不难。CFC4N想了一个方案，各位网友来批评指正一下。 腾讯可以做一个系统，各大论坛使用者提交论坛的主域名，腾讯再根据论坛使用者的主域名分配一个私钥，然后，论坛使用者将此私钥更改到论坛程序的认证部分文件中。当用户在其中的论坛用QQ登陆的时候，直接跳转到腾讯的登陆页，登陆成功之后，返回到用户登陆前的论坛，论坛再根据私钥来解密cookie，来判断此cookie是否生效。</li>
<li>无意中发现google对我们的BLOG www.cnxct.com 的快照更新了，而某度却还是那样。详情见下图</li>
</ul>
<p><div id="attachment_472" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/cfc4n_google_1.jpg" rel="lightbox[471]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/cfc4n_google_1-150x150.jpg" alt="" title="google更新cnxct.com 的快照截图" width="150" height="150" class="size-thumbnail wp-image-472" /></a><p class="wp-caption-text">google更新cnxct.com 的快照截图</p></div><br />
<div id="attachment_473" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/cfc4n_baidu_2.jpg" rel="lightbox[471]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/cfc4n_baidu_2-150x150.jpg" alt="" title="BAIDU未更新cnxct.com 的快照截图" width="150" height="150" class="size-thumbnail wp-image-473" /></a><p class="wp-caption-text">BAIDU未更新cnxct.com 的快照截图</p></div></p>
<p>呃。差点忘了，刚刚从QQ网络硬盘里，找出N年前收藏的工具SPXInstantScreenCapture，试用截图了，效果就是上图。其中，百度截图那张，有水印。原因是没注册，其实我有别人的注册码，只是我没用，打算中午用OD自己破解一下，很久不搞，基本的反汇编工具都生疏了。温习一下。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e7%ab%af%e5%8d%88%e8%8a%82%e4%b9%8b%e5%90%8e%e4%b8%80%e5%91%a8%e6%80%bb%e7%bb%93/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>coolcode转SyntaxHighlighter与Mysql正则表达式</title>
		<link>http://www.cnxct.com/coolcode%e8%bd%acsyntaxhighlighter%e4%b8%8emysql%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f/</link>
		<comments>http://www.cnxct.com/coolcode%e8%bd%acsyntaxhighlighter%e4%b8%8emysql%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 15:04:29 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[coolcode]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[SyntaxHighlighter]]></category>
		<category><![CDATA[反向引用]]></category>
		<category><![CDATA[正则]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/coolcode%e8%bd%acsyntaxhighlighter%e4%b8%8emysql%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/06/reg_11.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/reg_11-150x150.jpg" alt="" title="简单的正则表达式匹配字符串" width="150" height="150" class="alignleft sided inline" /></a>
blog的代码高亮插件原来是coolcode的，coolcode的高亮插件确实很酷，显示效果也很棒，但是占用的位子太大了。最近，我抽空改成SyntaxHighlighter。由于coolcode插件的开头标签是或者[coolcode]这样的，而SyntaxHighlighter是[code]这样的（或者其他）。遂只能想办法把老的格式转化成新的格式。当然，肯定用到正则表达式了。]]></description>
			<content:encoded><![CDATA[<p>blog的代码高亮插件原来是coolcode的，coolcode的高亮插件确实很酷，显示效果也很棒，但是占用的位子太大了。最近，我抽空改成SyntaxHighlighter。由于coolcode插件的开头标签是
<pre class="brush: plain; title: ; notranslate">&lt;coolcode&gt;</pre>
<p>或者[coolcode]这样的，而SyntaxHighlighter是
<pre class="brush: plain; title: ; notranslate">1。<br />
mysql里执行两句sql即可</p>
<pre class="brush: sql; title: ; notranslate">
UPDATE wp_posts SET post_content = REPLACE(post_content,'&lt;/coolcode&gt;','[\/code]');  //注意后面多了个反斜杠，记得去掉
UPDATE wp_posts SET post_content = REPLACE(post_content,'[/coolcode]','[\/code]');  //注意后面多了个反斜杠，记得去掉
</pre>
<p>总结：<br />
本文牵扯的正则表达式并无高级用法，都是平常很简单的用法。关于PCRE引擎正则表达式的递归(迭代),组命名，反向引用，零宽断言等，CFC4N会在以后的时间里，找合适的例子写出来。当然，这些高级用法，<a href="http://www.cnxct.com/cfc4n%e5%b0%8f%e8%af%95%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f/">CFC4N在帮朋友写的正则表达式</a>里已经用到了，大家可以看看，欢迎批评和指点。<br />
PS：如果需要coolcode转SyntaxHighlighter的完整PHP程序，留言即可，我抽空写出来。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/coolcode%e8%bd%acsyntaxhighlighter%e4%b8%8emysql%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

