<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[Y's Blog]]></title> 
<link>http://blog.sust.net.ru/index.php</link> 
<description><![CDATA[sust 陕西科技大学 科大漂亮MM该来的 Blog-网络红人的博客]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[Y's Blog]]></copyright>
<item>
<link>http://blog.sust.net.ru/read.php?150</link>
<title><![CDATA[使用.htaccess防盗链实战]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[搜集的教程]]></category>
<pubDate>Tue, 09 Dec 2008 15:39:35 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?150</guid> 
<description>
<![CDATA[ 
	<div id="textbody" class="content"><p>先解释一下图片防盗链和转向：</p> <p>图片防盗链有什么用？</p> <p>防止其它网站盗用你的图片，浪费你宝贵的流量。 </p> <p>图片转向有什么用？</p> <p>如果你的网站以图片为主，哪天发现月底没到流量就快用光了，那就可以利用图片转向，在不修改网页的前提下，把图片下载请求转向到其它空间(比如试用主机)，临时过渡。</p> <p>下面开始讲解，比如你的图片都在img目录下，那就在该目录下放一个名为 .htaccess 的文件，内容如下：</p> <div id="code0" class="altbg2" style="border: 1px solid #4c92d8; margin: 3px 2em 2em; padding: 5px 10px 10px; clear: both"><span style="font-size: 12px">RewriteEngine on<br /><br />RewriteCond %{HTTP_REFERER} !^$ [NC]<br />RewriteCond %{HTTP_REFERER} !</span><span style="font-size: 12px"><span style="font-size: 12px"><span style="color: #333333">oneter.com</span></span></span><span style="font-size: 12px"> [NC]<br />RewriteCond %{HTTP_REFERER} !zhuaxia.com [NC]<br />RewriteCond %{HTTP_REFERER} !google.com [NC]<br />RewriteCond %{HTTP_REFERER} !baidu.com [NC]<br />RewriteCond %{HTTP_REFERER} !bloglines.com [NC]<br /><br />RewriteRule .(jpg&#124;gif&#124;png&#124;bmp&#124;swf&#124;jpeg) /image/replace.gif [R,NC,L]<br /><br />RewriteRule ^(.*)$ http:&#92;/&#92;/image.simcole.cn&#92;/image&#92;/$1 [L]</span></div> <p>大概解释下：</p> <div id="code1" class="altbg2" style="border: 1px solid #4c92d8; margin: 3px 2em 2em; padding: 5px 10px 10px; clear: both"><span style="font-size: 12px">RewriteCond %{HTTP_REFERER} !^$ [NC]<br />RewriteCond %{HTTP_REFERER} !</span><span style="font-size: 12px"><span style="font-size: 12px"><span style="color: #333333">oneter.com</span></span></span><span style="font-size: 12px"> [NC]<br />RewriteCond %{HTTP_REFERER} !zhuaxia.com [NC]<br />RewriteCond %{HTTP_REFERER} !google.com [NC]<br />RewriteCond %{HTTP_REFERER} !baidu.com [NC]<br />RewriteCond %{HTTP_REFERER} !bloglines.com [NC]</span></div> <p>这部分是判断是否盗链，如果以上条件都成立(即访问图片的请求，既不是直接输入网址，也不是来自simcole.cn，也不是来自 zhuaxia.com，也不是来自google.com，也不是来自baidu.com，也不是来自bloglines.com 的话)，就执行下列转向：</p> <div id="code2" class="altbg2" style="border: 1px solid #4c92d8; margin: 3px 2em 2em; padding: 5px 10px 10px; clear: both"><span style="font-size: 12px">RewriteRule .(jpg&#124;gif&#124;png&#124;bmp&#124;swf&#124;jpeg) /image/replace.gif [R,NC,L]</span></div> <p><span style="font-size: 12px">意思是让所有盗链 img 目录下 jpg、gif、png、bmp、swf、jpeg 文件的网页，显示的图片都用 image 目录下的 replace.gif 图片替换掉。注意替换显示的图片不要放在设置防盗链的 img 目录下。如果照上面的规则判断出图片请求不是盗链的，就执行以下转向：</span></p> <span style="font-size: 12px"> <div id="code3" class="altbg2" style="border: 1px solid #4c92d8; margin: 3px 2em 2em; padding: 5px 10px 10px; clear: both"><span style="font-size: 12px">RewriteRule ^(.*)$ http:&#92;/&#92;/image.simcole.cn&#92;/image&#92;/$1 [L]</span></div> <span style="font-size: 12px">意思是对 img 目录下所有的请求都转向到目标服务器，比如有个图片原来的 url 是 </span><span style="font-size: 12px"><span style="color: #333333"><a href="http://www.oneter.com/img/girl.jpg" target="_blank">http://www.oneter.com/img/girl.jpg</a></span></span><span style="font-size: 12px"> ，现在就会转到 </span><span style="font-size: 12px"><span style="color: #333333"><a href="http://image.oneter.com/image/girl.jpg" target="_blank">http://image.oneter.com/image/girl.jpg</a></span></span><span style="font-size: 12px"> 去。当然了你得先把原服务器 img 目录下的文件统统拷贝到临时服务器的 image 目录下，转向才会真正可用。起到的效果就是把原服务器图片下载所占用的流量统统省下，让临时服务器来承受了</span></span></div><br/>Tags - <a href="tag.php?tag=.htaccess" rel="tag">.htaccess</a> , <a href="tag.php?tag=%E8%AE%BF%E7%9B%97%E9%93%BE" rel="tag">访盗链</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?149</link>
<title><![CDATA[Fuck的用法小结]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[搜集的教程]]></category>
<pubDate>Tue, 02 Dec 2008 13:50:30 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?149</guid> 
<description>
<![CDATA[ 
	<span>&nbsp;单独使用可以作为无任何意义的语气词。不过也可以放在动词和介词的词组中间应用以加强语气，比如get fuck out，shut fuck up，一般所跟随的介词以元音开头效果更好，一气呵成，不着痕迹。 <br /><br /><br />be fucked <br />严格的语法上来说呢，这个就是fuck的被动语态，8过实际应用中只要不是很顺心的状况呢，都可以用。一般对人不对事。有人倒霉了，基本上就是he's fucked了。 <br /><br /><br /><br />fucking <br />语法中有动词进行式做形容词的用法。这个fuck一加上ing的话就是包治百病天下无双了&hellip;&hellip;基本上所有的名词都可以形容。最为顺口的就是fucking asshole了。 <br /><br /><br /><br />fuck you <br />最常见的用法，矛头直指对方，快意恩仇。发音简单一学就会，一句在口可以走遍美国了。如果跟对方没什么计较的话fuck哪个也都可以，fuck him, fuck her, fuck them, fuck the states, fuck the world, 不过总是没有fuck you来得理直气壮言简意赅。 <br /><br /><br /><br />fuck me <br />嘿嘿，这个，一般只在特定场合特定行为中由特定人物表达。简单来说，就是女性叫床专用&hellip;&hellip;各位同学大家知道就可以了，这个，不用反复操练的&hellip;&hellip; <br /><br /><br /><br />fuck up <br />搞砸了，一般对事不对人，类似表达可以用screw up。 <br /><br /><br /><br />fuck off <br />收声闭嘴之极度表达。以程度类推效果大于hold your tounge大于shut up大于watch your mouth。 <br /><br /><br /><br />fuck with nb. <br />对某人找茬，故意戏弄某人。这个&hellip;&hellip;大家千万不要误解为与某人XX&hellip;&hellip; <br /><br /><br /><br />fuck you very much <br />这里的fuck you就比较活络了。不看语气和表情就很难判断对方的意图。因为他很有可能是在用另外一种方式说&ldquo;thank you very much&rdquo;。 <br /><br /><br /><br />motherfucker <br />跟老外比起来我们中华民族泱泱大国就文明多了。就算问候对方家长也是身体力行，或者&ldquo;X你妈&rdquo;或者&ldquo;X你大爷&rdquo;，老外比较懒，这些事情也都交给被骂的家伙去办了&hellip;&hellip; <br /><br /><br /><br />&quot;Fuck&quot; 是现代英语中最强烈,最有争议的粗语之一,这个词可能也是世界上最著名的亵渎语但何时这个词从一个友好用法变成亵渎用法却仍然无法解释一些证明显示,在一些英语为母语的地区,这个词直到17世纪才有一种攻击和亵渎的含义; 而另外一些证明却表明,早在16世纪的英国,这个词已经变成粗语因此一些诸如牛津大英字典的权威资料仍然无法确定这个粗语的来源,但倾向于相信撒克逊人 (英国人)起源说,然后再流传到英国殖民地,再到全世界 <br /><br />在现代英语中,&quot;Fuck&quot;是一种高度冒犯性的用词,是最为严厉的4字母词&quot;Fuck&quot; 原意就是XXXXX(操,干),但它往往被用作一个咒骂语和语气加强词一些&quot;Fuck&quot;原意的例子有: <br /><br />&quot;Let s fuck.&quot; (让我们操吧) <br />&quot;That was a good fuck.&quot; (那真是一次美妙的XXXXX) <br />&quot;I cant believe shes fucking him!&quot; (我不能相信她正在操他!) <br /><br /><br />&quot;I fucked my teacher!&quot; (我干了我老师) <br /><br />其他则是一些粗直语用法,但这些用法往往牵涉到性,譬如XXXXXX(fuck you)或者自慰(fuck yourself). <br /><br />&quot;Fuck you!&quot; or &quot;Go fuck yourself!&quot; (我不喜欢你,快滚开) <br />&quot;He&quot;s a dumb fuck.&quot; (他是个白痴) <br />&quot;Sorry, I fucked up your computer.&quot; (不好意思,我弄坏了你的电脑) <br />&quot;He s pretty fucked up.&quot; (他心理或者心情不稳定) <br />&quot;I fucked up on this test.&quot; (我这次测验做的很糟) <br />&quot;Lets fuck around for a couple hours.&quot; (让我们浪费2个小时好了) <br />&quot;Im fucked.&quot; (结果) <br />&quot;What the fuck!&quot; (到底刚才发生了什么?) <br />&quot;Shut the fuck up!&quot; (闭嘴) <br />&quot;Im so fucked up right now.&quot; (我已经烂醉或者被药物搞的晕晕乎乎了) <br />其他一些粗直用法则没有任何冒犯或者牵涉到性的意思而且当这个词被移除之后,这句句子的语意仍然保持不变譬如: <br /><br />&quot;None of your fucking business!&quot; (不关你&quot;鸟&quot;事) <br />&quot;Un-fucking-believable!&quot; (真难以置信!) <br />&quot;What a fucking great day outside!&quot; (外边的天气真&quot;他妈的&quot;的好) <br /><br /><br />2 fuck的用法小结 <br />&quot;Shut the fuck up!&quot; (你他妈的闭嘴 <br /><br />&quot;Abso-fuckin-lutley!&quot; &quot;绝对是!&quot; <br />&quot;Hey!, Why dont you go outside and play Hide-N-Go-Fuck-Yourself!&quot; &quot;嘿,为什么你不出去自己一个人玩? <br />&quot;Fuck!&quot; (当一些不快的事情发生) <br />&quot;Hes a great fucker!&quot; (他是一个非常好的家伙,并不意思他是一个非常好的性伙伴) <br />在最后一个例子中,&quot;Fucker&quot;这个词被用作一种赞赏,但这种用法并不常见譬如: &quot;You are a smart fucker (你是一个聪明的家伙)&quot;. 但正因为这种用法的粗鲁及不明确性, 除非对方是一个你非常熟悉的朋友,这个用法还是不要用的好因为有可能你的赞赏会被误解 <br /><br />&quot;Fuck&quot;这个词也是非常多样化的,譬如: <br /><br />&quot;Fucking fuck those fucking fuckers!&quot; (&quot;忘记那些另人讨厌的家伙吧.&quot;) &quot;Fucking fuckers fucking fucked!&quot; (&quot;它被弄坏了&quot;) <br /><br /><br />第二个例子很好的演示了这个词的多样性,它是一个名词,一个冠词,一个现在分词和一个形容词另外一个可以显示其多样性的例子是Mary Prankster 的歌:Mercyfuck (1998) <br /><br />I wish I could fuck all my sorrow away <br />And fuck til the dawn of the next fucking day <br />Fuck the chorus and verse, fuck the pain getting worse <br />Fuck it all til I burn <br /><br /><br />I wish I could fuck all of you til you see <br />Im the worst fuck-up in all history <br />Fuck your image and mine, fuck your limp valentine <br />Fuck it all til I learn <br />再补充一下&quot;Fuck&quot;这个词的常用法: <br /><br />动词 <br />可以当作一个及物动词: <br />He fucked her. (他操了她.) <br />或者不及物动词: <br />They fucked all night. (他们干了整个晚上) <br />或者对象非人的用法: <br />Im not going down there, fuck that, dude! (我不会下去的,操那东西,哥们!) <br />Im not doing that. Fuck outta here! (我不会做的,忘记它吧!) <br /><br />名词 <br />She is a real fuck. (没有特定的侮辱) <br />She is a good fuck. (特定的指向XXXXXX) <br />Eat my fuck. (是一种侮辱) <br />We had a good fuck last night. (作为一个性行为) <br />That was a total cluster fuck. (很多出错的事的当中一个) <br />Oh my fuck! (表明一种惊讶的意思) <br />Im being sent to Bumfuckegypt. (很有可能出自一个军事源头) <br /><br />感叹词 <br />Fuck作为感叹词时一般表示一种惊讶,不满或者愤怒的意思, 如: <br />Fuck! A punctured tire! <br />也可以表示一种正向的惊讶: <br />Fuck! Theyve hacked this computer! (噢!他们黑了这台电脑!) <br />Fuck! This is the best movie EVER! (噢!这是历史上最好的电影!) <br /><br />现在分词 <br />作为现在分词,Fucking (fuckin) 往往用来加强一个动词或者名词的语气它的正向意义往往多于其反向意义如: <br />My fucking boss made me work all weekend. (我那天杀的老板让我加整个周末的班) <br />She is fuckin hot. (她真他妈的性感) <br /><br />除此之外,Fuck的现在分词有时被插在一个词的中间这种用法叫作感叹插入语. 这种fucking插入法的规则是: &quot;fucking&quot;只能插入到一个多音节词的韵脚之间, 例如: <br />that was abso-fuckin-lutely cool! (那真他妈的酷!) <br />In-fucking-credible (难以置信) <br />fan-fucking-tastic (真棒) <br />un-fucking-believable (无法相信) <br />congratu-fucking-lations (祝贺祝贺) <br />whoop-dee-fucking-doo (%@@#@#) <br /><br />过去分词 <br />fuck的过去分词意思一样完全无用的,被损坏的,或者被搞糟的事物在形容一个人的时候,它表示一种筋疲力尽或者烂醉的意思 譬如: <br />The hard drive 无效ed, so now the database is fucked. (硬盘坏了所以现在数据库也被损坏了) <br />Your engines fucked because you forgot to change the oil! (你的引擎坏了,因你忘记换油了) <br />Now that the electricity is out, your computer is fucked. (没电了,你的电脑没用了) <br /><br /><br />3 fuck的用法小结 <br />You were completely fucked last night. (你昨晚真是糟糕透了) <br /><br /><br />动词短语 <br />&quot;To fuck up&quot;意思是破坏,&quot;to be fucked up&quot;往往意思烂醉,或者更正规的意思是身体或者心理上的伤害(常用于美国) 如: <br />The bouncer really fucked up that guy who kept causing trouble. (那个保镖把那个老是滋事的家伙打的够呛) <br />My sisters been really fucked up since her fianc&eacute; dumped her. 我的姐姐(妹妹)惨极了,因为她的未婚夫抛弃了她 <br />当在形容事物的时候,&quot;to be fucked up&quot;意思是这件事物是精神上或者其他方面上错误的 <br />She stole my wallet while I was passed out; thats so fucked up! (在我走出去的时候,她偷了我的钱包;那绝对是件错误的事) <br />&quot;To fuck over&quot; 意思背叛,或者通常不讨人喜欢的行为 <br />Yeah, he slept with my girlfriend. I cant believe he fucked me over like that! (他睡了我GF,我真的无法相信他如此背叛我!) <br />I got fucked over at work today &ndash; they promoted my assistant instead of me. (今天我在上班的时候被玩了: 他们提升了我助理,而不是我!) <br /><br />混成词 <br />F的发音有时被提高语调,以表示强烈的辱骂 <br />Thats fugly (fucking ugly). (那真他妈的丑) <br />You fucktard (fucking retard). (你他妈的智障) <br />You flooser! (fucking loser) (你他妈的失败者) <br /><br />讲演语气 <br />Fuck有时在讲演时被用作一种填补,用法很象um..., 或者like.. <br />Her name is, fuck... What was her name again? (她的名字是,恩,她的名字是什么?) <br /><br />the fuck 常用来加强语气，类似于&ldquo;到底&rdquo;、&ldquo;究竟&rdquo;、&ldquo;the heck&rdquo;、&ldquo;on <br />earth&rdquo; <br />、&ldquo;the hell&rdquo;等，在疑问词后。 <br /><br />例1 熟人间的问候： &quot;How the fuck are ya?&quot; <br />例2 疑问： &quot;What the fuck is（are）.......?&quot; <br />例3 不满： &quot;What the fuck is going on here?&quot; <br />例4 迷惘： &quot;Where the fuck are we.&quot; <br />例5 担心： &quot;Let's get the fuck out of here.&quot; <br />例6 怀疑： &quot;How the fuck did you do that?&quot; <br />get fucked , be fucked 被骗；遇到麻烦 <br />例7： &quot;I got fucked by the car dealer.&quot; <br />例8： &quot;I guess I'm fucked now.&quot; <br />Fucked again 表示绝望，&ldquo;完了&hellip;&hellip;&rdquo; <br />Fuck it 屈从，放弃 <br />例9： &quot;Oh, fuck it!&quot; <br />Fuck you ! 不用多解释了 <br />Fuck me. 表示厌恶 类似&ldquo;sth disgusts me&rdquo; <br />fucking 类似 the fuck ，作加强语气，不过还可作形容词，表示一些不爽的事物 <br /><br />例10： &quot;I don't understand this fucking business!&quot; <br />例11：根本不想 　&quot;I didn't fucking do it.&quot; <br />例12：骂人反击　 &quot;Up your fucking arse!&quot; <br />&quot;He's a fucking asshole.&quot; <br />例13：当然也有表示高兴的时候，类似于&ldquo;我他妈&hellip;&hellip;&rdquo; &quot;I fucking couldn't <br />be ha <br />ppier.&quot; <br />例14：放在一个词的中间（注意这种用法哦，国内较少见）增强语气： <br />&quot;UNFUCKINGBELI <br />EVABLE!&quot; <br />例15：表示时间 &quot;It's five fucking thirty.&quot; <br />Fuck off. &ldquo;滚开&rdquo; 类似&ldquo;go away&rdquo; <br />Fuck around. 胡闹 &ldquo;Quit ye fucking around!&rdquo; <br />Fuck up. 弄砸了 &ldquo;How did you fuck your exam up?&rdquo; <br />Fuck with 干涉 类似于&ldquo;interfere with&rdquo; <br />be fucked out 疲劳的，类似于&ldquo;exhausted&rdquo; <br />fuck 单独的用法： <br />例16：几乎 &quot;I know fuck all about it.&quot; <br />例17： 谁在乎过我了？&quot;Who really gives a fuck, anyhow?&quot; <br />　 <br />FUCK 一词并不邪恶，没有一些女生想象的那么坏，它在美国人的口语中出现的频 <br />率很高，就如同我们常说的&ldquo;我KAO&rdquo;。下面列举了一些名人说话中用过的FUCK： <br />　　 <br />广岛市市长　　 &quot;What the fuck was that?&quot;　　 <br /><br />4 fuck的用法小结 <br />Custer 上将 &quot;Where did all these fucking Indians come from?&quot; <br />泰坦尼克号船长 &quot;Where the fuck is all this water coming from?&quot; <br />约翰.列农 &quot;That&lsquo;s not a real fucking gun.&quot; <br />尼克森总统 &quot;Who&lsquo;s gonna fucking find out?&quot; <br />航天飞机的指挥官 &quot;Let the fucking woman drive.&quot; <br />爱因斯坦&quot;Any fucking idiot could understand that.&quot; <br />毕加索 &quot;It does so fucking look like her!&quot; <br />沃尔特.迪斯尼 &quot;Fuck a duck.&quot; <br />艾德门德.希拉里 &quot;Why?- Because its fucking there!&quot; <br />约翰.肯尼迪　　&quot;I need this parade like I need a fucking hole in my <br />head.&quot; <br /><br /><br />perhaps one of the most interesting words in the English Language today is the word &quot;Fuck&quot;. <br />也许英文中最有趣的单词之一就是今天要讲的Fuck。 <br /><br /><br /><br /><br />Out of all of the English words that begin with the letter &quot;F&quot;, Fuck is the only word that is refer to as the F-Word. <br />在所有以F开头的英文单词中，Fuck是唯一会被称为&ldquo;那个以F开头的单词&rdquo;。 <br /><br /><br /><br /><br />It&quot;s the one magical word just by its sound can describe pain, pleasure, hate and love. <br />这是一个神奇的词，仅仅通过它的发音就可以表达痛苦、愉悦、仇恨和喜爱。 <br /><br /><br /><br /><br />Fuck, as most words in the English language is derived from German the word &quot;frichen&quot; which means &quot;to strike&quot;. <br />Fuck正如大多数英语单词一样，来源于一个德语单词&quot;Frichen&quot;，这个单词的意思是&ldquo;击打&rdquo;。 <br /><br /><br /><br /><br />In English Fuck falls into many grammatical categories. <br />在英语中，Fuck又有多种用法。 <br /><br /><br /><br /><br />As a transitive verb , for instance, &quot;John Fucked Shirley&quot;; as a intransitive verb, &quot;Shirley Fucks. &quot; <br />作为一个及物动词，例如，John**Shirley；作为一个不及物动词，Shirley***。 <br /><br /><br /><br /><br />Its meanings not always sexual. <br />它的意思并不总是和性有关。 <br /><br /><br /><br /><br />It can be used as an adjective such as &quot;John&quot;s doing all the Fucking work&quot;. <br />它可以作为一个形容词，例如：John正在做所有TMD该死的工作。 <br /><br /><br /><br /><br />As an adverb, &quot;Shirley talks too Fucking much.&quot; <br />作为一个副词，Shirley的话真是太TMD多了。 <br /><br /><br /><br /><br />As an adverb enhancing and adjective, &quot;Shirley is Fucking beautiful&quot;. <br />作为副词或形容词时如果用升调读出，Shirley真是太TMD漂亮了。 <br /><br /><br /><br /><br />As a noun, &quot;I don&quot;t give a Fuck&quot;. <br />作为一个名词，我才不TMD管那么多。 <br /><br /><br /><br /><br />As part of a word, &quot;abso-Fucking-lutely&quot; or &quot;in-Fucking-credible&quot;. <br />作为词语的一部分，如TMD完全的，TMD难以置信的。 <br /><br /><br /><br /><br />And as almost every word in a sentence &quot;Fuck the Fucking Fuckers&quot;. <br />也可以被放在同一个句子中，**这个**的** <br /><br /><br /><br /><br />As you must realise there aren&quot;t too many words with the versatility of Fuck, as in these examples describing situations such as: <br />你应该注意到了，没有太多的单词像Fuck这样有多种功能，在如下的例子中描述不同的情况，如： <br /><br /><br /><br /><br />Fraud : &quot;I got Fucked by the car dealer.&quot; <br />受骗：我被车贩子骗了。 <br /><br /><br /><br /><br />Dismay: &quot;Ah Fuck it&quot; . <br />沮丧：我* <br /><br /><br /><br /><br />Trouble: &quot;I guess I&quot;m really Fucked now&quot; . <br />麻烦：我猜我这次真的栽了。 <br /><br /><br /><br /><br />Aggression: &quot;Don&quot;t Fuck with me ｂｏｄｙ&quot; . <br />挑衅：小子，不关你的事。 <br /><br /><br /><br /><br />Difficulty: &quot;I don&quot;t understand this Fucking question&quot; <br />困难：我不明白这个TMD问题。 <br /><br /><br /><br /><br />Inquiry: &quot;Who the Fuck was that?&quot; <br />质疑：那TMD是谁？ <br /><br /><br /><br /><br />Dissatisfaction: &quot;I don&quot;t like what the Fuck is going on here&quot; <br />不满：我不喜欢这里正在发生的$%$&amp;%^&amp; <br /><br /><br /><br /><br />Incompetence: &quot;He&quot;s a Fuck up&quot; <br />无奈：他就是一个** <br /><br /><br /><br /><br />Dismissal: &quot;Why don&quot;t you go outside and play hide and go Fuck yourself?&quot; <br />打发：你为什么不出去$^$^#^# <br /><br /><br /><br /><br />I&quot;m sure you can think of much more examples. <br />我肯定你还可以想到更多例子。 <br /><br /><br /><br /><br />With all of these multipurpose applications, how can anyone be offended when you use the word? <br />在各种各样的情况下，怎么用这个词得罪别人呢？ <br /><br /><br /><br /><br />We say use this unique flexible word more often in your daily speech. <br />我们可以在日常对话中更多的使用这个唯一的多样的词。 <br /><br /><br /><br /><br />It will identify the quality of your character immediately. <br />它能立即让你显得有性格。 <br /><br /><br /><br /><br />Say it loudly and proudly&mdash;&mdash;FUCK YOU!</span><br/>Tags - <a href="tag.php?tag=fuck" rel="tag">fuck</a> , <a href="tag.php?tag=%E6%95%99%E7%A8%8B" rel="tag">教程</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?148</link>
<title><![CDATA[牛人泡妞的聊天记录，每句都出彩啊 ]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[乱七又八糟]]></category>
<pubDate>Tue, 02 Dec 2008 13:13:38 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?148</guid> 
<description>
<![CDATA[ 
	<span>牛人泡妞的聊天记录，每句都出彩啊！<br />偶然间听到爆笑谷的大名，据说此人不但具备周星星同学无厘头搞笑风格，其文学修养，综合实力等更是无人能敌，迷倒了一大批MM。不愧是网络第一泡妞高手呀！后来我一搜索爆笑谷三个字就找到了一大堆他的经典泡妞语录。我把这些泡妞语录背熟以后，在聊天室中如鱼得水，投怀送抱的MM不计其数。以下是他的经典泡妞聊天记录，口笨的朋友可以学习一下。有种的高手可以向他挑战，把你们泡MM的经典语录也发上来，让大家看看哪个才是泡妞界的高手。 <br /><br />蓝精灵：你到底是一个怎样的男人呢？ <br />　　　　爆笑谷：嗯，世界上所有语言都是难以评价的 <br />　　　　蓝精灵：这么拽？ <br />　　　　爆笑谷：只有用你的肢体来触摸，才能感受得到我的好 <br />　　　　蓝精灵：恶心！ <br />　　　　爆笑谷：其实我这个人真的很不错，是运动型的男人 <br />　　　　蓝精灵：真的吗？ <br />　　　　爆笑谷：我喜欢一切运动 <br />　　　　蓝精灵：好，我欣赏 <br />　　　　爆笑谷：尤其喜欢床上运动 <br />　　　　蓝精灵：色狼！ <br />　　　　爆笑谷：我说的是在床上练瑜伽，你想什么哪？ <br />　　　　蓝精灵：呸！ <br />　　　　爆笑谷：我还喜欢一切圆的球类 <br />　　　　蓝精灵：什么球？ <br />　　　　爆笑谷：尤其是女人身上的两个球！ <br />　　　　蓝精灵：！！又来了 <br />　　　　爆笑谷：我说的是女人的眼球，明眸善睐，多美啊！ <br />　　　　蓝精灵：晕！ <br />　　　　爆笑谷：没关系了，知道你是个美女，所以我很喜欢你了，尤其是你身上的两个球&hellip; <br />　　　　蓝精灵：呸呸！！ <br />　　　　爆笑谷：我说的是真的哟 <br />　　　　蓝精灵：我发现我对你也开始有了一种无法言表的、异样的感觉&hellip;&hellip; <br />　　　　爆笑谷：耶！我一直以为我对你是自作多情，看来还没有了，呼呼 <br />　　　　蓝精灵：当然不是自作多情，根本就是一厢情愿嘛！ <br />　　　　爆笑谷：啊！你不是说有感觉吗？ <br />　　　　蓝精灵：是啊，有感觉，一种想吐的感觉！！ <br />---------------------------------------------------------------------------------------------------------------- <br /><br /><br /><br />蓝精灵：好无聊呀 <br />　　　　爆笑谷：是啊，我也觉得无聊 <br />　　　　蓝精灵：对一切都失去了兴趣了 <br />　　　　爆笑谷：生活失去了颜色 <br />　　　　蓝精灵：对，一片空白 <br />　　　　爆笑谷：偶尔，有点黄色了，嘿嘿 <br />　　　　蓝精灵：打你头！ <br />　　　　爆笑谷：打破的话，就会多了一点红色~~ <br />　　　　蓝精灵：我和男朋友分手了！ <br />　　　　爆笑谷：恭喜 <br />　　　　蓝精灵：不用了，知道你想恭喜我解脱了 <br />　　　　爆笑谷：错！我是恭喜你男朋友终于摆脱你了！ <br />　　　　蓝精灵：你！！！ <br />　　　　爆笑谷：分开其实很好 <br />　　　　蓝精灵：是吗 <br />　　　　爆笑谷：女人的容貌是别人的，女人的知识是别人的，女人的身体也是别人的，只有快乐是自己的 <br />　　　　蓝精灵：有点意思 <br />　　　　爆笑谷：男人更惨 <br />　　　　蓝精灵：怎么惨了？ <br />　　　　爆笑谷：男人的钱包是老婆的，男人的智慧是老婆的，男人的身体也是老婆的 <br />　　　　蓝精灵：快乐是自己的？ <br />　　　　爆笑谷：男人有了老婆，哪里还有快乐？！ <br />　　　　蓝精灵：好可怜啊，那男人总得有不属于老婆的地方吧 <br />　　　　爆笑谷：是啊，和老婆在一起的时候，心却是属于别的MM的 <br />　　　　蓝精灵：是吗？ <br />　　　　爆笑谷：心里想着别的MMSC时的样子&hellip;&hellip; <br />　　　　蓝精灵：啊？！ <br />　　　　爆笑谷：我是说别的MMSC翻筋斗时的样子！ <br />　　　　蓝精灵：晕！ <br />------------------------------------------------------------------------------------------------- <br /><br /><br /><br /><br />云边之雪：你在吗？怎么不见你上线？ <br />　　　　爆笑谷：心无时不跳，我无处不在。 <br />　　　　云边之雪：原来是个&ldquo;隐君子&rdquo; <br />　　　　爆笑谷：隐名免灾祸，隐身免烦恼。 <br />　　　　云边之雪：不知道&ldquo;小隐于野，大隐于市&rdquo;吗？ <br />　　　　爆笑谷：知人知面不知心，隐名隐身难隐情。 <br />　　　　云边之雪：哇，好难懂啊，你学哲学的？ <br />　　　　爆笑谷：学文学的都是傻子，学哲学的都是疯子。 <br />　　　　云边之雪：真精辟啊，你是不是经常这样在网上泡妞？ <br />　　　　爆笑谷：流汗流血不流泪，泡茶泡吧不泡妞。 <br />　　　　云边之雪：好酷呀，可是人不可能没有感情呀！ <br />　　　　爆笑谷：蒸桑拿蒸馒头不争名利，弹吉它弹棉花不谈感情 <br />　　　　云边之雪：我开始流汗了，你真是个牛人！ <br />　　　　爆笑谷：玩什么都别玩爱情，信什么也别信男人。 <br />　　　　云边之雪：嗯，至理名言，你受过感情的伤呀？ <br />　　　　爆笑谷：爱有多深，恨有多深。 <br />　　　　云边之雪：怎么感觉那么沧桑啊。 <br />　　　　爆笑谷：女人因为成熟而沧桑，男人因为沧桑而成熟。 <br />　　　　云边之雪：有点难懂，但又很有道理。 <br />　　　　爆笑谷：男人善于花言巧语，女人喜欢花前月下。 <br />　　　　云边之雪：你是怪物吧！ <br />　　　　爆笑谷：每个人都是怪物，每句话都是真理。 <br />　　　　云边之雪：天啊，和你生活在一起会累死了，肯定没人会嫁给你。 <br />　　　　爆笑谷：笨男人要结婚，笨女人要减肥。 <br />　　　　云边之雪：我要哭了！ <br />　　　　爆笑谷：爱与恨都是寂寞的空气，哭与笑表达同样的意义。 <br />　　　　云边之雪：哭和笑怎么能一样，去死吧！ <br />　　　　爆笑谷：苦与乐都是财富，生与死都要绚丽。 <br />　　　　云边之雪：和你说话真累，其实你不懂女人心。 <br />　　　　爆笑谷：女人希望男人表露心灵，男人希望女人裸露身体。 <br />　　　　云边之雪：嗯这句话有道理，你有没有女朋友？ <br />　　　　爆笑谷：黄脸老婆易寻，红颜知己难觅。 <br />　　　　云边之雪：和你结婚会不会开心？ <br />　　　　爆笑谷：男人的痛苦从结婚开始，女人的痛苦从认识男人开始。 <br />　　　　云边之雪：天啊，那还是不要接近你了&hellip;&hellip; <br />　　　　爆笑谷：最易接近的是身体，最难接近的是心灵。 <br />　　　　云边之雪：你喜欢怎样的女孩子？ <br />　　　　爆笑谷：女人喜欢的男人越成熟越好，男人喜欢的女孩越单纯越好。 <br />　　　　云边之雪：不是吧，我怎么听说男人对不单纯的女人也感兴趣？ <br />　　　　爆笑谷：好男人应在床上勇猛，好女人应在床上放荡。 <br />　　　　云边之雪：哈哈色狼的尾巴露出来了！ <br />　　　　爆笑谷：男人好色称为色狼，男人不好色称为色盲。 <br />　　　　云边之雪：你讲话很搞笑呀。 <br />　　　　爆笑谷：世间纷繁万般无奈，心头只求片刻安宁 <br />　　　　云边之雪：下次还能和你聊吗？ <br />　　　　爆笑谷：做男人无能会使女人寄希望于未来，做女人失败会使男人寄思念于过去 <br />　　　　云边之雪：哈哈，你的意思是我们现在就见面？ <br />　　　　爆笑谷：心动不如行动，说到不如做到。 <br />　　　　云边之雪：OK，我决定了，去见你！ <br />　　　　爆笑谷：有缘人终成正果，有情人终成网友！ <br />---------------------------------------------------------------------------------------------------------------------- <br /><br /><br /><br />蓝精灵：你为什么总是隐身啊？ <br />　　　　爆笑谷：怕被美女骚扰啊 <br />　　　　蓝精灵：拽吧你，你以为你是谁啊？ <br />　　　　爆笑谷：我很优秀的，一个优秀的男人，不需要华丽的外表，不需要有渊博的知识，不需要有沉重的钱袋，只要他的思想够丰富，学会在茫茫网络中隐藏自己的锋芒，就足够了&hellip; <br />　　　　蓝精灵：哇，高人啊！ <br />　　　　爆笑谷：不错，本人不矮，1米85 <br />　　　　蓝精灵：你真是一个优秀的男人吗？ <br />　　　　爆笑谷：当然，我从小就很优秀，小学到初中，一直在班里任重要职务 <br />蓝精灵：班长？ <br />　　　　爆笑谷：卫生小组组长。 <br />　　　　蓝精灵：真的好重要哇~~ <br />　　　　爆笑谷：相信你也是一个很优秀的人 <br />　　　　蓝精灵：嗯，想想，从小到大，倒是得了不少荣誉 <br />　　　　爆笑谷：说说看 <br />　　　　蓝精灵：小学时候得到讲故事大赛第三名 <br />　　　　爆笑谷：一共3个人参加吧！ <br />　　　　蓝精灵：中学时候长跑考试得了一次第一 <br />　　　　爆笑谷：倒数的吧 <br />　　　　蓝精灵：我写的文章都在学校公开栏展出 <br />　　　　爆笑谷：写的检查吧 <br />　　　　蓝精灵：大学时候还参 <br /><br /><br /><br /><br />加过学校舞台剧的演出，从第一场到最后一场，我全都出场了&hellip; <br />　　　　爆笑谷：演一块石头吧&hellip;&hellip; <br />　　　　蓝精灵：现在人们还都说我是一个才女呢 <br />　　　　爆笑谷：嗯，你是做裁缝的吧，裁女！ <br />　　　　蓝精灵：555，居然全被你猜中了！ <br />------------------------------------------------------------------------------------------------------------------------ <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />冰玫瑰：男人跟女人聊天，是不是都怀有什么目的 <br />　　　　爆笑谷：是啊，所有的男人都只有一个目的，就是把女人聊SC <br />　　　　冰玫瑰：啊！ <br />　　　　爆笑谷：当然了，我跟别人男人是不一样的 <br />　　　　冰玫瑰：你的目的是？ <br />　　　　爆笑谷：让女人把我聊SC！！ <br />　　　　冰玫瑰：你好厉害，你成功了几个？ <br />　　　　爆笑谷：数数啊，嗯，大约有一百多个吧！ <br />　　　　冰玫瑰：啊，那么多，不会吧，怎么做的？ <br />　　　　爆笑谷：常常都是聊到深夜，然后我对女网友说，你真会聊，厉害，我不行了，今天我已经很困了，我要SC去睡觉了！然后，我就SC去睡觉了&hellip;&hellip; <br /><br /><br /><br /><br />爆笑谷：好 <br />　　　　妹红雷：好 <br />　　　　爆笑谷：聊吗 <br />　　　　妹红雷：不 <br />　　　　爆笑谷：为什么 <br />　　　　妹红雷：忙 <br />　　　　爆笑谷：忙什么 <br />　　　　妹红雷：玩 <br />　　　　爆笑谷：玩什么 <br />　　　　妹红雷：游戏 <br />　　　　爆笑谷：什么游戏 <br />　　　　妹红雷：好玩的 <br />　　　　爆笑谷：什么好玩的 <br />　　　　妹红雷：烦 <br />　　　　爆笑谷：烦就跟我聊 <br />　　　　妹红雷：滚 <br />　　　　爆笑谷：地不干净 <br />　　　　妹红雷：靠 <br />　　　　爆笑谷：给你肩膀 <br />　　　　妹红雷：找死啊 <br />　　　　爆笑谷：&ldquo;死&rdquo;在字典961页 <br />　　　　妹红雷：晕 <br />　　　　爆笑谷：我有止晕药 <br />　　　　妹红雷：我服了 <br />　　　　爆笑谷：服了药就不晕了 <br />　　　　妹红雷：大哥 <br />　　　　爆笑谷：认你这个妹妹了 <br />　　　　妹红雷：拜托 <br />　　　　爆笑谷：拜可以，不用脱 <br />　　　　妹红雷：我要疯了 <br />　　　　爆笑谷：我打120 <br />　　　　妹红雷：你神仙 <br />　　　　爆笑谷：不要迷信 <br />　　　　妹红雷：还让人活吗 <br />　　　　爆笑谷：有了我你会活得更精彩 <br />　　　　妹红雷：555 <br />　　　　爆笑谷：三五香烟虽好，但有害健康 <br />　　　　妹红雷：去死吧 <br />　　　　爆笑谷：我在网吧，不是死吧 <br />　　　　妹红雷：求你放过我 <br />　　　　爆笑谷：好，告诉我手机号我就不说了 <br />　　　　妹红雷：要号干嘛 <br />　　　　爆笑谷：改给你发短信</span><br/>Tags - <a href="tag.php?tag=%E6%B3%A1%E5%A6%9E" rel="tag">泡妞</a> , <a href="tag.php?tag=%E8%81%8A%E5%A4%A9" rel="tag">聊天</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?147</link>
<title><![CDATA[写给女孩们的话]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[心情和故事]]></category>
<pubDate>Sat, 16 Feb 2008 18:38:23 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?147</guid> 
<description>
<![CDATA[ 
	<strong><span style="font-size: x-small; color: #660066; font-family: 楷体_GB2312">要告诉你们的话，你必须找到除了爱情之外，能够使你用双脚坚强站在大地上的东西。你要找到谋生的方式。现在考虑不晚了。我从来不以为学历有什么重要，天才都不是科班，但，不是科班，连龙套都跑不了。　　 <br /></span></strong><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">你必须把那些浮如飘絮的思绪，渐渐转化为清晰的思路和简单的文字。华丽和漂浮都不易长久。你要知道，给予文字阅读快感是不够的，内容，思想，境界，灵魂，精神和智慧，这些才重要。　</span><br />　 <span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">不要多看那些和你一个路数的女作家的文字。不要琐碎，无病呻吟。不要想到什么就写。不要流于小感伤和小感动。 </span><br />女孩，我要你相信温暖，美好，信任，尊严，坚强这些老掉牙的字眼。我不要你颓废，空虚，迷茫，糟践自己，伤害别人。我不要你把自己处理得一团糟。　　 <br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">节制自己的感情。不是任何人都能要。体验生活，是另外一回事，并不意味着堕落和放纵。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">千万不要认同那些伪装的酷和另类。他们是无事可做的人找出来放任自己无事可做 的借口。真正的酷是在内心。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">你要有强大的内心。要有任凭时间流逝，不会磨折和屈服的信念。　　 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">不是因为在象牙塔中，才说出我爱世界这样的话。是知道外面的黑，脏，丑陋之后，还要说出这样的话。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">女孩，好好去爱，去生活。青春如此短暂，不要叹老。偶尔可以停下来休息，但是别蹲下来张望。走了一条路的时候，记得别回头看。　　　　　　 </span><br />时不时问问自己，自己在干吗。 伤心和委屈的时候，要嚎啕大哭。哭完洗完脸，拍拍自己的脸，挤出一个微笑给 自己看。不要揉，否则第二天早上会眼睛肿。 <br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">给自己一个远大的前程和目标。记得常常仰望天空。记住仰望天空的时候也看看脚下。 </span><br />任何时候，任何人问你，有过多少次恋爱，答案是两次。一次是他爱我，我不爱他。一次是我爱他，他不爱我。好的爱情永远在下一次。别给同一个男人两次伤害你的机会。 <br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">不要为欲望羞耻，好好享受，但绝不忍受男人的侮辱和怠慢。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">相信我，女孩，男人多的是，比三条腿的青蛙多得多。别轻易说出&ldquo;爱&rdquo;。　　 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">相信你的直觉。　　 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">不要招惹别人的男人，除非你非常非常爱他，并且，他非常非常值得爱。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">不要招惹寻找与前女友相似，和他母亲，姐姐相似女人的男人。不要招惹浪子，文艺青年和中年男子。别招惹太清纯的男人。别和没心没肺的人在一起。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">别把犯贱当真爱。一个男人作践自己来取悦你的时候，千万不要因此感动。这个烟头烫在他身上，下一个就可能烫在你身上。　　 </span><br />看看一个男人的朋友们是什么样的，注意他的朋友们对待女人的态度。还有，千万别相信一个不准备将你介绍给他的朋友圈子的男人。一个男人只肯喊你&ldquo;宝贝&rdquo;的时候，坚持要他喊你的名字。一个男人不再来找你的时候，就不要再去找他。　　 <br />不要相信在恋爱上用手段的人。分手时不要口出恶言。吸取教训，但不要后悔。后悔没有用。 别干撕照片，烧信，撕日记这样一类三流爱情电视剧中才有人干的事。　　 <br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">相信爱情。相信好男人还存在，还未婚，还在茫茫人海中寻觅你。千万别说&ldquo;男人没一个好东西&rdquo;这样使别人误以为你阅人无数的话。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">答应我，永远不要去做那种午夜背着行李，从一个男朋友家，流落到另一个男朋友家的女人。 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">爱物质，适当地。永远知道精神更重要。比那些名表，名牌，时装，更加美丽的是你自己。 </span><br />别瞧不起劳动人民。不要为劳动羞耻。土地不脏，汗味不难闻。尊重那些似乎生活状况不如你的人，因为这样才是尊重自己。永远体恤那些生活在底层的人们。我们，并不特别娇贵。　　　　　　 <br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">不要小看一分钱。不妨自己去挣挣看。　　　　　　 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">被朋友伤害了的时候，别怀疑友情，但提防背叛你的人。原谅，但并不遗忘。做人存几分天真童心，对朋友保持一些侠义之情。　　　　　　 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">要快乐，要开朗，要坚韧，要温暖。这和性格无关。　　　　　　 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">我担心你太沉默，有时要强悍一点，被欺负的时候，一定要讨回来！但是不要记恨。小人之见，随他们去好了。怜悯，会使你高贵。　　　　　　 </span><br /><span style="padding-right: 1px; padding-left: 1px; filter: glow(color=#000000,strength=3); padding-bottom: 1px; color: #ffffff; padding-top: 1px; height: 10px">最后， 要原谅这世界和自己。要告诉自己，你值得拥有最好的一切。</span><br/>Tags - <a href="tag.php?tag=%E5%BF%83%E6%83%85%E6%95%85%E4%BA%8B" rel="tag">心情故事</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?146</link>
<title><![CDATA[一些错误代码含义详解]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[搜集的教程]]></category>
<pubDate>Thu, 14 Feb 2008 10:10:36 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?146</guid> 
<description>
<![CDATA[ 
	<span class="content"><a href="http://hi.baidu.com/weimade/blog/item/33b6a619c102394542a9adce.html"><a href="http://hi.baidu.com/weimade/blog/item/33b6a619c102394542a9adce.html" target="_blank">http://hi.baidu.com/weimade/blog/item/33b6a619c102394542a9adce.html</a></a><br />错误类型：<br />一、未使用二进制上传<br /><br /></span><span class="content"><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Fatal error: This encoded file is corrupted. Please refer to <a href="http://www.zend.com/support/support_faq.php?id=loader_file_corrupt" target="_blank">http://www.zend.com/support/support_faq.php?id=loader_file_corrupt</a> for further help in <br /><br />/webhome/****.com/web/www/index.php on line 0 </td></tr></tbody></table></td></tr></tbody></table><p><br />二、数据表中缺少字段<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">An error was encountered <br />Boka SiteEngine<br />数据库错误<br />错误信息1054: Unknown column 'tuijian' in 'where clause'<br /><br />出现错误的查询信息是<br />SELECT * FROM boka_product WHERE tuijian=1 AND classid IN ('1','0')ORDER BY id DESC LIMIT 4</td></tr></tbody></table></td></tr></tbody></table><p><br />三、服务器限制了网站使用内存的大小为8M，现在已经超过<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 5898240 bytes) <br /><br /><br />四、这个是模板错误，header.php的529行所指出的模板，该模板的79行出错<br />[code]in /webhome/***.com/web/www/header.php(529) : eval()'d code on line 79</td></tr></tbody></table></td></tr></tbody></table><p><br />五、数据库表不存在<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">An error was encountered <br />Boka SiteEngine<br /><br />1146: Table 'test.boka_settings' doesn't exist<br /><br /><br />SELECT value FROM boka_settings WHERE variable='defaultstyleid'</td></tr></tbody></table></td></tr></tbody></table><p><br />六、 未安装或者数据库的用户名密码错误<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">An error was encountered <br />Boka SiteEngine<br /><br />1045: Access denied for user: 'root@localhost' (Using password: YES) </td></tr></tbody></table></td></tr></tbody></table><p><br />七、查询语句有错误<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Boka SiteEngine<br />数据库错误<br />错误信息1064: You have an error in your SQL syntax near 'ORDER BY sequence ASC,id ASC' at line 1<br /><br />出现错误的查询信息是<br />UPDATE gzhy_newsclass SET ishidden ='1' WHERE id = '38' ORDER BY sequence ASC,id ASC </td></tr></tbody></table></td></tr></tbody></table><p><br />八、文件过期<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">There is a fatal error,the file has expired</td></tr></tbody></table></td></tr></tbody></table><p><br />九、数据库出错，需要修复数据库或者重新启动数据库？<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">An error was encountered <br />Boka SiteEngine<br /><br />2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)</td></tr></tbody></table></td></tr></tbody></table><p><br />十、<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Warning: Unexpected character in input: ' ' (ASCII=4) state=1 in c:&#92;program files&#92;siteengine&#92;siteenginephp&#92;www&#92;index.php on line 97<br /><br />Warning: Unexpected character in input: ' ' (ASCII=5) state=1 in c:&#92;program files&#92;siteengine&#92;siteenginephp&#92;www&#92;index.php on line 97<br /><br />Parse error: parse error, unexpected T_STRING in c:&#92;program files&#92;siteengine&#92;siteenginephp&#92;www&#92;index.php on line 97</td></tr></tbody></table></td></tr></tbody></table><p><br />十一、这是语言管理中的language表里面有些字段没有引号，有些新增模块有这样的问题<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Boka SiteEngine<br />数据库错误<br />错误信息1064: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'home']'' at line 1</td></tr></tbody></table></td></tr></tbody></table><p><br />出现错误的查询信息是<br />UPDATE boka_language<br /><br />十二、不存在此函数<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Fatal error: Call to undefined function: buildhtml() in /usr/boka/www.lzj.bsa.cn/admin/news.php on line 894</td></tr></tbody></table></td></tr></tbody></table><p><br />十三、服务器执行时间超时.修改php.ini里的设置<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Fatal error: Maximum execution time of 30 seconds exceeded in c:&#92;program files&#92;siteengine&#92;siteenginephp&#92;www&#92;lib&#92;tar.php on line 101 Fatal error: Maximum execution time of <br /><br />30 seconds exceeded in c:&#92;program files&#92;siteengine&#92;siteenginephp&#92;www&#92;lib&#92;cookie.php on line 174</td></tr></tbody></table></td></tr></tbody></table><p><br />十四、调用了不存在的类<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Fatal error: Call to a member function on a non-object in e:&#92;boka&#92;d.com&#92;admin&#92;product.php on line 1291</td></tr></tbody></table></td></tr></tbody></table><p><br />十五、ZEND版本不匹配？<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Fatal error: Incompatible file format: The encoded file has format ID 2006022801, whereas the Optimizer can read up to 2002062301 in e:&#92;website&#92;d.com&#92;install.php on line 0</td></tr></tbody></table></td></tr></tbody></table><p><br />十六、不能建立windows下的Mysql服务进程<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">cannot create windows service for mysql.error:0</td></tr></tbody></table></td></tr></tbody></table><p><br />十七、数据表错误，修复数据表.(检查数据库的表。通过phpmyadmin即可修复)<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Discuz! info: MySQL Query Error<br /><br />User: 球球妈<br />Time: 2006-7-26 10:50am<br />Script: /forums/redirect.php<br /><br />SQL: SELECT f.fid, t.tid, f.*, ff.* , f.fid AS fid<br />FROM cdb_forums f, cdb_threads t<br />LEFT JOIN cdb_forumfields ff ON ff.fid=f.fid <br />WHERE t.tid='109118' AND t.displayorder&gt;='0' AND f.fid=t.fid LIMIT 1<br />Error: Can't open file: 'cdb_threads.MYI'. (errno: 145)<br />Errno.: 1016<br /><br />Similar error report has beed dispatched to administrator before.</td></tr></tbody></table></td></tr></tbody></table><p><br />十七，环境zend未安装<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Zend Optimizer not installed</td></tr></tbody></table></td></tr></tbody></table><p><br />十八，安装是没有任何反应，输入install.php面空白。<br />环境错误提示被屏蔽，察看文件是否用二进制传送或者是zend是否有安装。<br /><br />十九、数据库出现<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">too many connections</td></tr></tbody></table></td></tr></tbody></table><p><br />数据库链接数太多，修改mysql的最大链接数。<br /><br />二十、输入安装install.php提示<br />install.php 不允许执行原因是： <br />脚本权限错误：不能设置为同组可写！<br /><br />服务器端配置： <br /><br />Server Administrator/Contact: [no address given] <br />Server Name: www.***.com <br />Server Port: 80 <br />Server Protocol: HTTP/1.1 <br /><br />访问请求数据： <br /><br />User Agent/Browser: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon) <br />Request Method: GET <br />Remote Address: 221.222.177.106 <br />Remote Port: 30066 <br /><br />请检查install.php的文件属性是否为644。<br /><br />二十一、访问页面提示：<br /><br /></p><table border="0" cellspacing="0" cellpadding="0" width="90%"><tbody><tr><td class="smalltxt">代码:</td><td align="right"><a href="http://www.siteengine.net/thread_22_740_1.html###"><span style="color: #777777">[拷贝到剪贴板]</span></a> </td></tr><tr><td colspan="2"><table border="0" cellspacing="1" cellpadding="10" width="100%" bgcolor="#cccccc"><tbody><tr><td width="100%" style="word-break: break-all" bgcolor="#f8f8f8">Warning: main(/data/home/zn00s1/htdocs/data/language/.php): failed to open stream: No such file or directory in /data/home/zn00s1/htdocs/admin/global.php on line 62 </td></tr></tbody></table></td></tr></tbody></table><p><br />这个错误是由于数据库恢复不正常。请核实2个数据库的版本是否一致。<br /><br />二十二、在2003下执行install.php文件，点击&quot;下一步&quot;的按钮点击不下去.<br />请检查2003下的IE的安全设置为中。<br /><a href="http://www.ca029.com/"></a></p></span><br /><a href="http://www.ca029.com/"></a><br/>Tags - <a href="tag.php?tag=%E6%8A%80%E5%B7%A7" rel="tag">技巧</a> , <a href="tag.php?tag=%E9%97%AE%E9%A2%98" rel="tag">问题</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?145</link>
<title><![CDATA[跟我学正则表达式! 半小时精通正则表达式! ]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[搜集的教程]]></category>
<pubDate>Tue, 05 Feb 2008 18:20:04 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?145</guid> 
<description>
<![CDATA[ 
	想必很多人都对正则表达式都头疼.今天,我以我的认识,加上网上一些文章,希望用常人都可以理解的表达方式.来和大家分享学习经验.<br /><br />&nbsp;&nbsp;开篇,还是得说说 ^&nbsp;&nbsp;和&nbsp;&nbsp;$&nbsp;&nbsp;他们是分别用来匹配字符串的开始和结束，以下分别举例说明 <br /><br /><br />&quot;^The&quot;: 开头一定要有&quot;The&quot;字符串; <br />&quot;of despair$&quot;:&nbsp;&nbsp;结尾一定要有&quot;of despair&quot; 的字符串; <br /><br /><br />那么,<br />&quot;^abc$&quot;: 就是要求以abc开头和以abc结尾的字符串，实际上是只有abc匹配 <br />&quot;notice&quot;: 匹配包含notice的字符串 <br /><br /><br />你可以看见如果你没有用我们提到的两个字符（最后一个例子），就是说 模式（正则表达式） 可以出现在被检验字符串的任何地方，你没有把他锁定到两边 <br /><br />接着,说说 '*', '+',和 '?', <br />他们用来表示一个字符可以出现的次数或者顺序. 他们分别表示：<br />&quot;zero or more&quot;相当于{0,}, <br />&quot;one or more&quot;相当于{1,}, <br />&quot;zero or one.&quot;相当于{0,1},&nbsp;&nbsp;这里是一些例子: <br /><br /><br />&quot;ab*&quot;:&nbsp;&nbsp;和ab{0,}同义,匹配以a开头,后面可以接0个或者N个b组成的字符串(&quot;a&quot;, &quot;ab&quot;, &quot;abbb&quot;, 等); <br />&quot;ab+&quot;: 和ab{1,}同义,同上条一样，但最少要有一个b存在 (&quot;ab&quot;, &quot;abbb&quot;, 等.); <br />&quot;ab?&quot;:和ab{0,1}同义,可以没有或者只有一个b; <br />&quot;a?b+$&quot;: 匹配以一个或者0个a再加上一个以上的b结尾的字符串. <br /><br />要点, '*', '+',和 '?'只管它前面那个字符.<br /><br /><br />你也可以在大括号里面限制字符出现的个数，比如 <br /><br /><br />&quot;ab{2}&quot;: 要求a后面一定要跟两个b（一个也不能少）(&quot;abb&quot;); <br />&quot;ab{2,}&quot;: 要求a后面一定要有两个或者两个以上b(如&quot;abb&quot;, &quot;abbbb&quot;, 等.); <br />&quot;ab{3,5}&quot;: 要求a后面可以有2－5个b(&quot;abbb&quot;, &quot;abbbb&quot;, or &quot;abbbbb&quot;). <br /><br /><br /><br />现在我们把一定几个字符放到小括号里，比如：<br /><br />&quot;a(bc)*&quot;: 匹配 a 后面跟0个或者一个&quot;bc&quot;; <br />&quot;a(bc){1,5}&quot;: 一个到5个 &quot;bc.&quot; <br /><br /><br />还有一个字符 '│', 相当于OR 操作: <br /><br /><br />&quot;hi│hello&quot;: 匹配含有&quot;hi&quot; 或者 &quot;hello&quot; 的 字符串; <br />&quot;(b│cd)ef&quot;: 匹配含有 &quot;bef&quot; 或者 &quot;cdef&quot;的字符串; <br />&quot;(a│b)*c&quot;: 匹配含有这样多个（包括0个）a或b，后面跟一个c <br />的字符串; <br /><br /><br />一个点('.')可以代表所有的单一字符,不包括&quot;n&quot;<br /><br />如果,要匹配包括&quot;n&quot;在内的所有单个字符,怎么办?<br /><br />对了,用'[n.]'这种模式.<br /><br /><br />&quot;a.[0-9]&quot;: 一个a加一个字符再加一个0到9的数字 <br />&quot;^.{3}$&quot;: 三个任意字符结尾 . <br /><br /><br /><br /><br />中括号括住的内容只匹配一个单一的字符 <br /><br /><br />&quot;[ab]&quot;: 匹配单个的 a 或者 b ( 和 &quot;a│b&quot; 一样); <br />&quot;[a-d]&quot;: 匹配'a' 到'd'的单个字符 (和&quot;a│b│c│d&quot; 还有 &quot;[abcd]&quot;效果一样); 一般我们都用[a-zA-Z]来指定字符为一个大小写英文<br />&quot;^[a-zA-Z]&quot;: 匹配以大小写字母开头的字符串 <br />&quot;[0-9]%&quot;: 匹配含有 形如 x％ 的字符串 <br />&quot;,[a-zA-Z0-9]$&quot;: 匹配以逗号再加一个数字或字母结尾的字符串 <br /><br /><br />你也可以把你不想要得字符列在中括号里，你只需要在总括号里面使用'^' 作为开头 &quot;%[^a-zA-Z]%&quot; 匹配含有两个百分号里面有一个非字母的字符串. <br /><br />要点:^用在中括号开头的时候,就表示排除括号里的字符 <br /><br />为了PHP能够解释，你必须在这些字符面前后加'',并且将一些字符转义. <br /><br />不要忘记在中括号里面的字符是这条规路的例外&mdash;在中括号里面, 所有的特殊字符，包括(''), 都将失去他们的特殊性质 &quot;[*+?{}.]&quot;匹配含有这些字符的字符串.<br /><br />还有,正如regx的手册告诉我们: &quot;如果列表里含有 ']', 最好把它作为列表里的第一个字符(可能跟在'^'后面). 如果含有'-', 最好把它放在最前面或者最后面, or 或者一个范围的第二个结束点[a-d-0-9]中间的&lsquo;-&rsquo;将有效. <br /><br />看了上面的例子,你对{n,m}应该理解了吧.要注意的是,n和m都不能为负整数,而且n总是小于m. 这样,才能 最少匹配n次且最多匹配m次. 如&quot;p{1,5}&quot;将匹配 &quot;pvpppppp&quot;中的前五个p<br /><br />下面说说以开头的<br /><br />b 书上说他是用来匹配一个单词边界,就是...比如'veb',可以匹配love里的ve而不匹配very里有ve<br /><br />B 正好和上面的b相反.例子我就不举了<br /><br /><br />好,我们来做个应用:<br /><br />如何构建一个模式来匹配 货币数量 的输入 <br /><br />构建一个匹配模式去检查输入的信息是否为一个表示money的数字。我们认为一个表示money的数量有四种方式： &quot;10000.00&quot; 和 &quot;10,000.00&quot;,或者没有小数部分, &quot;10000&quot; and &quot;10,000&quot;. 现在让我们开始构建这个匹配模式: <br /><br />^[1-9][0-9]*$ <br /><br />这是所变量必须以非0的数字开头.但这也意味着 单一的 &quot;0&quot; 也不能通过测试. 以下是解决的方法: <br /><br />^(0│[1-9][0-9]*)$ <br /><br />&quot;只有0和不以0开头的数字与之匹配&quot;，我们也可以允许一个负号在数字之前: <br /><br />^(0│-?[1-9][0-9]*)$ <br /><br />这就是: &quot;0 或者 一个以0开头 且可能 有一个负号在前面的数字.&quot; 好了,现在让我们别那么严谨，允许以0开头.现在让我们放弃 负号 , 因为我们在表示钱币的时候并不需要用到. 我们现在指定 模式 用来匹配小数部分: <br /><br />^[0-9]+(.[0-9]+)?$ <br /><br />这暗示匹配的字符串必须最少以一个阿拉伯数字开头. 但是注意，在上面模式中 &quot;10.&quot; 是不匹配的, 只有 &quot;10&quot; 和 &quot;10.2&quot; 才可以. （你知道为什么吗） <br /><br />^[0-9]+(.[0-9]{2})?$ <br /><br />我们上面指定小数点后面必须有两位小数.如果你认为这样太苛刻,你可以改成: <br /><br />^[0-9]+(.[0-9]{1,2})?$ <br /><br />这将允许小数点后面有一到两个字符. 现在我们加上用来增加可读性的逗号（每隔三位）, 我们可以这样表示: <br /><br />^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$ <br /><br />不要忘记 '+' 可以被 '*' 替代 如果你想允许空白字符串被输入话 (为什么?). 也不要忘记反斜杆 &rsquo;&rsquo; 在php字符串中可能会出现错误 (很普遍的错误). <br /><br />现在，我们已经可以确认字符串了, 我们现在把所有逗号都去掉 str_replace(&quot;,&quot;, &quot;&quot;, $money) 然后在把类型看成 double然后我们就可以通过他做数学计算了. <br /><br /><br />再来一个:<br /><br />构造检查email的正则表达式 <br /><br />在一个完整的email地址中有三个部分: <br />1. 用户名 (在 '@' 左边的一切), <br />2.'@',<br />3. 服务器名(就是剩下那部分). <br /><br />用户名可以含有大小写字母阿拉伯数字,句号 ('.'), 减号('-'), and 下划线 ('_'). 服务器名字也是符合这个规则,当然下划线除外. <br /><br />现在, 用户名的开始和结束都不能是句点. 服务器也是这样. 还有你不能有两个连续的句点他们之间至少存在一个字符，好现在我们来看一下怎么为用户名写一个匹配模式: <br /><br />^[_a-zA-Z0-9-]+$ <br /><br />现在还不能允许句号的存在. 我们把它加上: <br /><br />^[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*$ <br /><br />上面的意思就是说: &quot;以至少一个规范字符（除了.）开头,后面跟着0个或者多个以点开始的字符串.&quot; <br /><br />简单化一点, 我们可以用 eregi()取代 ereg().eregi()对大小写不敏感, 我们就不需要指定两个范围 &quot;a-z&quot; 和 &quot;A-Z&quot; &ndash; 只需要指定一个就可以了: <br /><br />^[_a-z0-9-]+(.[_a-z0-9-]+)*$ <br /><br />后面的服务器名字也是一样,但要去掉下划线: <br /><br />^[a-z0-9-]+(.[a-z0-9-]+)*$ <br /><br />好. 现在只需要用&rdquo;@&rdquo;把两部分连接: <br /><br />^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$ <br /><br /><br />这就是完整的email认证匹配模式了,只需要调用 <br /><br />eregi(&lsquo;^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$ &rsquo;,$eamil) <br /><br />就可以得到是否为email了 <br />正则表达式的其他用法 <br /><br />提取字符串 <br /><br />ereg() and eregi() 有一个特性是允许用户通过正则表达式去提取字符串的一部分(具体用法你可以阅读手册). 比如说,我们想从 path/URL 提取文件名 &ndash; 下面的代码就是你需要: <br /><br />ereg(&quot;([^/]*)$&quot;, $pathOrUrl, $regs); <br />echo $regs[1]; <br /><br />高级的代换 <br /><br />ereg_replace() 和 eregi_replace()也是非常有用的: 假如我们想把所有的间隔负号都替换成逗号: <br /><br /><br />ereg_replace(&quot;[ nrt]+&quot;, &quot;,&quot;, trim($str));<br /><br />最后,我把另一串检查EMAIL的正则表达式让看文章的你来分析一下.<br /><br />&quot;^[-!#$%&amp;'*+./0-9=?A-Z^_`a-z{&#124;}~]+'.'@'.'[-!#$%&amp;'*+/0-9=?A-Z^_`a-z{&#124;}~]+.'.'[-!#$%&amp;'*+./0-9=?A-Z^_`a-z{&#124;}~]+$&quot;<br /><br />如果能方便的读懂,那这篇文章的目的就达到了.<br /><br/>Tags - <a href="tag.php?tag=php" rel="tag">php</a> , <a href="tag.php?tag=php%E6%AD%A3%E5%88%99" rel="tag">php正则</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?144</link>
<title><![CDATA[PHP和正则表达式]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[学习与实践]]></category>
<pubDate>Tue, 05 Feb 2008 18:17:08 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?144</guid> 
<description>
<![CDATA[ 
	一个正则表达式是一个特定的格式化模式，可以用来找出一个字符串在另一个字符串中的使用情况。几个编程语言，包括Visual Basic,Perl,JavaScript和PHP都支持正则表达式，希望在这篇入门指导的结束，Mitchell(作者自己)可以让你在PHP程序中 能应用一些基本的正则表达式。正则表达式是在各种各样的程序语言中突出的古怪特征中的一种，但是由于它们看起来是很难的一个概念，所以很多开发者就把它们 放到了角落里，忘记了它们的存在。<br /><br />让我们先来看看什么是正则表达式，为什么你要在PHP程序中用到它们。<br /><br />什么是正则表达式?<br /><br />你对从一个不错的老的基于控制的文本编辑器中分离出像BBEdit和notepad的程序，有什么看法呢？两个都支持文本输入，可以让你保存文本到文件中，但是现在的文本编辑器也支持其它功能，包括查找&ndash;代替工具，这让编辑一个文本文件相当容易。<br />&nbsp; &nbsp;&nbsp;&nbsp;正则表达式也是相似的，只是更好一些。正则表达式可以被认为一个极其高级的查找-替换工具，让我们从痛苦中摆脱出来：不必再写定制的数据确认例子来检查电子邮件地址或者来确认电话号码的格式是正确的，如此等等。<br />&nbsp; &nbsp;&nbsp;&nbsp;任何程序中最普通的函数之一就是数据有效性检查，PHP捆绑了一些文本检查函数，允许我们用正则表达式匹配一个字符串，确认有一个空格，有一个问号，等等。<br />&nbsp; &nbsp;&nbsp;&nbsp;你不知道的可能是，正则表达式可以简单装备吗，当你掌握了一些正则表达式时(这个正则表达式可以用来告诉正则表达式引擎一个字符串中我们想要匹配的部分)，你会自问为什么会把正则表达式扔到角落里这么久，^_^。<br />&nbsp; &nbsp;&nbsp;&nbsp;PHP有两套函数，用来处理两种类型的正则表达式:Perl5兼容模式，和Posix标准兼容模式。在这篇文章中我们将看看ereg函数，用遵照 Posix标准的搜索表达式工作。虽然它们并没有Perl5模式那样强大，但是一种不错的学习正则表达式的方法。如果你对PHP支持的Perl5兼容正则 表达式感兴趣，可以到PHP.net网站找一些关于preg函数的细节。<br />&nbsp; &nbsp;&nbsp;&nbsp;PHP有六个函数来处理正则表达式，它们都把一个正则表达式作为它们的第一个参数，列出如下：<br /><br />ereg: 最常用的正则表达式函数, ereg 允许我们搜索跟一个正则表达式匹配的一个字符串. <br />ereg_replace: 允许我们搜索跟正则表达式匹配的一个字符串，并用新的字符串代替所有这个表达式出现的地方。 <br />eregi: 和ereg几乎是一样效果，不过忽略大小写。 <br />eregi_replace: 和ereg_replace有着一样的搜索-替换功能，不过忽略大小写. <br />split: 允许我们搜索和正则表达式匹配的字符串，并且以字符串集合的方式返回匹配结果. <br />spliti: split函数忽略大小写的版本.<br />为什么使用正则表达式? <br /><br />&nbsp; &nbsp;&nbsp; &nbsp; 如果你不断地建立不同的函数来检查或者操作字符串的一部分，现在你可能要放弃所有的这些函数，取而代之的用正则表达式。如果你对下列的问题都答&ldquo;是的&rdquo;，那么你肯定要考虑使用正则表达式了：<br /><br />你是否正在写一些定制的函数来检查表单数据（比如在电子信箱地址中的一个@，一个点）? <br />你是否写一些定制的函数，在一个字符串中循环每个字符，如果这个字符匹配了一个特定特征（比如它是大写的，或者它是一个空格），那么就替换它?<br />&nbsp; &nbsp;&nbsp; &nbsp;除了是令人不舒服的字符串检查和操作方法，如果没有有效率地写代码，上述的两条也会使你的程序慢下来。你是否更倾向于用下面的代码检查一个电子信箱地址呢:<br /><br />&lt;?php<br />function validateEmail($email) <br />{ <br />&nbsp; &nbsp;&nbsp; &nbsp;$hasAtSymbol = strpos($email, &quot;@&quot;); <br />&nbsp; &nbsp;&nbsp; &nbsp;$hasDot = strpos($email, &quot;.&quot;);<br />&nbsp; &nbsp;&nbsp; &nbsp;if($hasAtSymbol &amp;&amp; $hasDot) <br />&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;return true; <br />&nbsp; &nbsp;&nbsp; &nbsp;else <br />&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;return false; <br />}<br />echo validateEmail(&quot;<a href="mailto:mitchell@devarticles.com">mitchell@devarticles.com</a>&quot;);<br />?&gt; <br />... <br />或者使用下面的代码:<br /><br />&lt;?php<br />function validateEmail($email) <br />{ <br />&nbsp; &nbsp; return ereg(&quot;^[a-zA-Z]+@[a-zA-Z]+.[a-zA-Z]+$&quot;, $email); <br />}<br />echo validateEmail(&quot;<a href="mailto:mitchell@devarticles.com">mitchell@devarticles.com</a>&quot;);<br />?&gt; <br />可以肯定的是，第一个函数比较容易，而且看起来结构也不错。但是如果我们用上面的下一个版本的email地址检查函数不是更容易吗？<br /><br />&nbsp; &nbsp; 上面展示的第二个函数只用了正则表达式，包括了对ereg函数的一个调用。Ereg 函数返回true或者false,来声明它的字符串参数是否和正则表达式相匹配。<br /><br />很多编程者避开正则表达式，只因为它们（在一些情况下）比其它的文本处理方法更慢。正则表达式可能慢的原因是因为它们涉及把字符串在内存中拷贝和粘贴，因 为正则表达式的每一个新的部分都对应匹配一个字符串。但是，从我对正则表达式的经验来说，除非你在文本中几百个行运行一个复杂的正则表达式，否则性能上的 缺陷都可以忽略不计，当把正则表达式作为输入数据检查工具时，也很少出现这种情况。<br /><br />正则表达式语法<br />在你可以匹配一个字符串到正则表达式之前，你必须先建立正则表达式。开始的时候，正则表达式的语法有点古怪，表达式中的每一个短语代表某个类型的搜索特征。下列是一些最普通的正则表达式，也都对应着一个如何使用它的例子:<br /><br />字符串头部<br />搜索一个字符串的头部，用^,例如<br /><br />&lt;?php echo ereg(&quot;^hello&quot;, &quot;hello world!&quot;); ?&gt; <br />将返回 true, 但是<br /><br />&lt;?php echo ereg(&quot;^hello&quot;, &quot;i say hello world&quot;); ?&gt; <br />将返回 false, 因为hello不在字符串&rdquo;I say hello world&rdquo;的头部。<br />字符串尾部 <br /><br />搜索字符串尾部，用$,例如：<br /><br />&lt;?php echo ereg(&quot;bye$&quot;, &quot;goodbye&quot;); ?&gt; <br />将返回true, 但是<br /><br />&lt;?php echo ereg(&quot;bye$&quot;, &quot;goodbye my friend&quot;); ?&gt; <br />将返回 false,因为bye不在字符串&rdquo;goodbye my friend&rdquo;的尾部.<br /><br />任意的单个字符 <br />搜索任意字符，用点(.),例如：<br /><br />&lt;?php echo ereg(&quot;.&quot;, &quot;cat&quot;); ?&gt; <br />将返回true,但是<br /><br />&lt;?php echo ereg(&quot;.&quot;, &quot;&quot;); ?&gt; <br />将返回false,因为我们的要搜索字符串没有包含字符。你可以用花括号随意告诉正则表达式引擎它要匹配多少个单个字符。如果我只想匹配5个字符，我可以这样用ereg:<br /><br />&lt;?php echo ereg(&quot;.{5}$&quot;, &quot;12345&quot;); ?&gt; <br />上面的这段代码告诉正则表达式引擎当且仅当至少5个连续的字符出现字符串的尾部时返回true.我们也可以限制连续出现的字符的数目：<br /><br />&lt;?php echo ereg(&quot;a{1,3}$&quot;, &quot;aaa&quot;); ?&gt; <br />在上面的例子里，我们已经告诉正则表达式引擎，我们的搜索字符串来匹配表达式，它在尾部必须有介于1和3个的&rdquo;a&rdquo;字符。<br /><br />&lt;?php echo ereg(&quot;a{1,3}$&quot;, &quot;aaab&quot;); ?&gt; <br />上面的例子将不会返回true，虽然有三个&rdquo;a&rdquo;字符在搜索字符串里，但是它们不是在字符串的尾部。如果我们把结尾字符串匹配$从正则表达式中去掉，那么这个字符串是匹配的。<br />我们也可以告诉正则表达式引擎来匹配至少有确定数目的字符在一行，如果它们存在的，可以匹配更多。 我们可以这样做：<br /><br />&lt;?php echo ereg(&quot;a{3,}$&quot;, &quot;aaaa&quot;); ?&gt; <br />零或多次重复字符<br />为了告诉正则表达式引擎一个字符可能存在，也可以重复，我们用*字符。这里的两个例子都将返回true.<br /><br />&lt;?php echo ereg(&quot;t*&quot;, &quot;tom&quot;); ?&gt; <br />&lt;?php echo ereg(&quot;t*&quot;, &quot;fom&quot;); ?&gt; <br />即使第二个例子不包含&rdquo;t&rdquo;这个字符，但仍旧返回ture,因为*表示字符可以出现，但不是必须出现。事实上，任何普通的字符串模式都会使上面的ereg调用返回true，因为&rsquo;t&rsquo;字符是可选的.<br /><br /><br />一或多次重复字符<br />为了告诉正则表达式引擎一个字符必须存在，也可以重复不止一次，我们用+字符，像<br /><br />&lt;?php echo ereg(&quot;z+&quot;, &quot;i like the zoo&quot;); ?&gt; <br />下面的例子也会返回true:<br /><br />&lt;?php echo ereg(&quot;z+&quot;, &quot;i like the zzzzzzoo!&quot;); ?&gt; <br />零或一次重复字符 <br />我们也可以告诉正则表达式引擎，一个字符必须是或者只存在一次，或者没有。我们用?字符来做这项工作，就像<br /><br />&lt;?php echo ereg(&quot;c?&quot;, &quot;cats are fuzzy&quot;); ?&gt; <br />如果我们愿意，我们完全可以从上面的搜索字符串中删除&rsquo;c&rsquo;，这个表达式会仍旧返回true.&rsquo;?&rsquo; 的意思是一个&rsquo;c&rsquo;可以出现在搜索字符串的任何地方，但不是必须的。<br /><br />正则表达式语法 (续) <br />空格字符 <br />为了匹配一个搜索字符串中的空格字符，我们用预定义Posix的类，[[:space]].方括号标明连续字符的相关性，&rdquo;:space:&rdquo;是实际要匹配 的类（在这种情形下，是任何空白字符）。空白包括tab字符，新行字符，空白字符。或者，如果搜索字符串必须包含只有一个空格，而不是一个tab或者新行 字符，你可以用一个空格字符(&quot; &quot;)。在大多数情况下，我倾向于使用&quot;:space:&quot;，因为这意味着我的意图不仅仅是单个空格字符，这点很容易被忽视。这里有一些Posix-标准预定 义类，<br />有一些我们可以作为正则表达式的部分的一些Posix-标准预定义类，包括[:alnum:], [:digit:], [:lower:]等等。 完整的列表可以在这里查看<br /><br />我们可以像这样匹配单个空白字符：<br /><br />&lt;?php echo ereg(&quot;Mitchell[[:space:]]Harper&quot;, &quot;Mitchell Harper&quot;); ?&gt; <br />我们也可以通过在表达式后用?字符来告诉正则表达式引擎匹配没有空白或者一个空白。<br /><br />&lt;?php echo ereg(&quot;Mitchell[[:space:]]?Harper&quot;, &quot;MitchellHarper&quot;); ?&gt; <br />模式分组<br />相关的模式可以在方括号里分在一起。很容易用[a-z]和[A-Z]指定只有一个小写字母或者一列大写字母以搜索字符串的一部分存在。<br /><br />&lt;?php<br />// 要求从第一个到最后一个都是小写字母 <br />echo ereg(&quot;^[a-z]+$&quot;, &quot;johndoe&quot;); // 返回true<br />?&gt; <br />或者像<br /><br />&lt;?php<br />// 要求从第一个到最后一个都是大写字母<br />ereg(&quot;^[A-Z]+$&quot;, &quot;JOHNDOE&quot;); // 返回 true?<br />?&gt; <br />我们也可以告诉正则表达式引擎，我们希望或者是小写字母，或者是大写字母。我们只要把[a-z]和[A-Z]模式结合在一起就可以做到。<br /><br />&lt;?php echo ereg(&quot;^[a-zA-Z]+$&quot;, &quot;JohnDoe&quot;); ?&gt; <br />在上面的例子里，如果我们能匹配&quot;John Doe&quot;,而不是&quot;JohnDoe&quot;，将是非常有意义的。我们用下面的正则表达式来做这个：<br /><br />^[a-zA-Z]+[[:space:]]{1}[a-zA-Z]+$ <br />很容易搜索一个数字字符串<br /><br />&lt;?php echo ereg(&quot;^[0-9]+$&quot;, &quot;12345&quot;); ?&gt; <br />词语分组 <br />不仅仅搜索模式可以分组，我们也可以用圆括号把相关的搜索词语进行分组。<br /><br />&lt;?php echo ereg(&quot;^(John&#124;Jane).+$&quot;, &quot;John Doe&quot;); ?&gt; <br />在上面的例子中，我们有一个字符串头部字符，紧跟着&quot;John&quot;或者&quot;Jane&quot;,至少有一个其它字符，然后一个字符串尾部字符。所以&hellip;<br /><br />&lt;?php echo ereg(&quot;^(John&#124;Jane).+$&quot;, &quot;Jane Doe&quot;); ?&gt; <br />...将也匹配我们的搜索模式<br /><br />特殊字符的情形<br />因为一些字符要用在一个搜索模式的明确分组或者语法上，像在(John&#124;Jane)中的圆括号，我们需要告诉正则表达式引擎来屏蔽这些字符，加工它们使之 成为被搜索字符串的一部分，而不是搜索表达式的一部分。我们所用的方法称为&ldquo;字符转义&rdquo;，涉及到将任何&ldquo;专用符号&rdquo;加上反斜杠。所以，例如，如果我想在我 的搜索中包含&rsquo;&#124;&rsquo;，那么我就可以这样做<br /><br />&lt;?php echo ereg(&quot;^[a-zA-z]+&#124;[a-zA-z]+$&quot;, &quot;John&#124;Jane&quot;); ?&gt; <br />这里只是少量的一些你要转义的字符，你必须转义^, $, (, ), ., [, &#124;, *, ?, +,&nbsp;&nbsp;and { 。<br />希望你现在对正则表达式实际上有多么强大有了一点点感觉了。现在让我们看两个用正则表达式来检查数据中一个字符串的例子。<br />正则表达式例子<br />例子1 <br />让我们把第一个例子做的相当简单，检验一个标准的URL.一个标准的URL(没有端口号),有三个部分构成：<br /><br />[协议]://[域名]<br /><br />让我们从匹配URL的协议部分开始,并且让它只能用http或者ftp.我们可以用下面的正则表达式做到这点：<br /><br />^(http&#124;ftp)<br />^字符特指字符串的头部，利用圆括号把http和ftp围住，且用&ldquo;或者&rdquo;符号(&#124;)将它们分开，我们告诉正则表达式引擎http和ftp两者之一必须在字符串的开头。<br /><br />一个域名通常由<a href="http://www.somesite.com/" target="_blank"><a href="http://www.somesite.com" target="_blank">www.somesite.com</a></a>构成，但是可以随意选择要不要www部分。为了例子简单，我们只允许.com,.net,和.org的域名是在考虑之中的。我们最好这样对正则表达式中的域名部分表示如下：<br /><br />(<a href="http://www.%29/?.+.%28com%7Cnet%7Corg%29$" target="_blank"><a href="http://www.)?.+.(com&#124;net&#124;org)$" target="_blank">www.)?.+.(com&#124;net&#124;org)$</a></a> <br />把所有的东西放在一起，我们的正则表达式就可以用作检查一个域名，如：<br /><br />&lt;?php<br />function isValidDomain($domainName) <br />{ <br /><br />return ereg(&quot;^(http&#124;ftp)://(<a href="http://www.)?.+.(com&#124;net&#124;org)$&quot;" target="_blank">www.)?.+.(com&#124;net&#124;org)$&quot;</a>, $domainName); <br />}<br />//真(true) <br />echo isValidDomain(&quot;<a href="http://www.somesite.com&quot;);" target="_blank">http://www.somesite.com&quot;);</a><br />//真(true)<br />echo isValidDomain(&quot;<a href="ftp://somesite.com&quot;);" target="_blank">ftp://somesite.com&quot;);</a><br />//假 (false)<br />echo isValidDomain(&quot;<a href="ftp://www.somesite.fr&quot;);" target="_blank">ftp://www.somesite.fr&quot;);</a><br />//假 (false) <br />echo isValidDomain(&quot;<a href="http://www.somesite.com&quot;);" target="_blank">www.somesite.com&quot;);</a><br />?&gt; <br />例子二 <br />因为我居住在澳大利亚悉尼，让我们检查一个典型的澳大利亚国际电话号码。澳大利亚国际电话号码的格式如下：<br />+61x xxxx-xxxx<br />第一个x是区号，其它的都是电话号码。检查以'+61'开头且紧跟一个在2到9之间的区号的电话号码，我们用下面的正则表达式：<br /><br />^+61[2-9][[:space:]] <br />注意，上面的搜索模式把'+'字符用''转义，以便于可以在搜索中包含，不至于被解释为一个正则表达式。[2-9]告诉正则表达式引擎我们需要包含一个2到9之间的数字。[[:space:]]类则告诉正则表达式期望在这里有一个空白。<br /><br /><br />这里是电话号码剩下的搜索模式：<br /><br />[0-9]{4}-[0-9]{4}$ <br />这里没有什么不寻常的地方，我们只是告诉正则表达式引擎电话号码可用的数字，它必须是4个数字的组合，跟着一个连接符，再跟着另一个4个数字的组合，然后一个字符串尾部字符。<br />把完整的正则表达式放在一起，放进一个函数，我们可以用代码来检查一些澳大利亚国际电话号码：<br /><br />&lt;?php<br />function isValidPhone($phoneNum) <br />{ <br />echo ereg(&quot;^+61[2-9][[:space:]][0-9]{4}-[0-9]{4}$&quot;, $phoneNum); <br />}<br />// 真（true） <br />echo isValidPhone(&quot;+619 0000-0000&quot;);<br />// 假（false） <br />echo isValidPhone(&quot;+61 00000000&quot;);<br />//假（ false） <br />echo isValidPhone(&quot;+611 00000000&quot;);<br />?&gt; <br />总结<br />正则表达式用一些不适合书写和重复的代码来检查一个字符串。在最后的几页里，我们已经讲解了所有的Posix标准正则表达式的基础，包括字符，分组和PHP ereg函数。我们也知道了怎么用正则表达式来检查一些PHP中简单的字符串。<br /><br />译者注释：本人英文不怎么好，可能一些地方有出入。本文中的字符类其实是我们所说的字符簇<br />经典正则表达式<br />正则表达式用于字符串处理，表单验证等场合，实用高效，但用到时总是不太把握，以致往往要上网查一番。我将一些常用的表达式收藏在这里，作备忘之用。本贴随时会更新。<br /><br />匹配中文字符的正则表达式： [u4e00-u9fa5]<br /><br />匹配双字节字符(包括汉字在内)：[^x00-xff]<br /><br />应用：计算字符串的长度（一个双字节字符长度计2，ASCII字符计1）<br /><br />String.prototype.len=function(){return this.replace([^x00-xff]/g,&quot;aa&quot;).length;}<br /><br />匹配空行的正则表达式：n[s&#124; ]*r<br /><br />匹配HTML标记的正则表达式：/&lt;(.*)&gt;.*&lt;/1&gt;&#124;&lt;(.*) /&gt;/ <br /><br />匹配首尾空格的正则表达式：(^s*)&#124;(s*$)<br /><br />应用：javascript中没有像vbscript那样的trim函数，我们就可以利用这个表达式来实现，如下：<br /><br />String.prototype.trim = function()<br />{<br />return this.replace(/(^s*)&#124;(s*$)/g, &quot;&quot;);<br />}<br /><br />利用正则表达式分解和转换IP地址：<br /><br />下面是利用正则表达式匹配IP地址，并将IP地址转换成对应数值的Javascript程序：<br /><br />function IP2V(ip)<br />{<br />re=/(d+).(d+).(d+).(d+)/g //匹配IP地址的正则表达式<br />if(re.test(ip))<br />{<br />return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1<br />}<br />else<br />{<br />throw new Error(&quot;Not a valid IP address!&quot;)<br />}<br />}<br /><br />不过上面的程序如果不用正则表达式，而直接用split函数来分解可能更简单，程序如下：<br /><br />var ip=&quot;10.100.20.168&quot;<br />ip=ip.split(&quot;.&quot;)<br />alert(&quot;IP值是：&quot;+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))<br /><br />匹配Email地址的正则表达式：w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*<br /><br />匹配网址URL的正则表达式：<a href="http://%28/" target="_blank"><a href="http://(" target="_blank">http://(</a></a>[w-]+.)+[w-]+(/[w- ./?%&amp;=]*)?<br /><br />利用正则表达式去除字串中重复的字符的算法程序：<br /><br />var s=&quot;abacabefgeeii&quot;<br />var s1=s.replace(/(.).*1/g,&quot;$1&quot;)<br />var re=new RegExp(&quot;[&quot;+s1+&quot;]&quot;,&quot;g&quot;)<br />var s2=s.replace(re,&quot;&quot;) <br />alert(s1+s2) //结果为：abcefgi<br /><br />我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法，最终没有找到，这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符，再以重复的字符建立第二个表达式，取到不重复的字符，两者串连。这个方法对于字符顺序有要求的字符串可能不适用。<br /><br />得用正则表达式从URL地址中提取文件名的javascript程序，如下结果为page1<br /><br />s=&quot;<a href="http://www.9499.net/page1.htm&quot;" target="_blank">http://www.9499.net/page1.htm&quot;</a><br />s=s.replace(/(.*/){0,}([^.]+).*/ig,&quot;$2&quot;)<br />alert(s)<br /><br />利用正则表达式限制网页表单里的文本框输入内容：<br /><br />用正则表达式限制只能输入中文：onkeyup=&quot;value=value.replace(/[^u4E00-u9FA5]/g,'')&quot; onbeforepaste=&quot;clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))&quot;<br /><br />用正则表达式限制只能输入全角字符： onkeyup=&quot;value=value.replace(/[^uFF00-uFFFF]/g,'')&quot; onbeforepaste=&quot;clipboardData.setData('text',clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))&quot;<br /><br />用正则表达式限制只能输入数字：onkeyup=&quot;value=value.replace(/[^d]/g,'') &quot;onbeforepaste=&quot;clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))&quot;<br /><br />用正则表达式限制只能输入数字和英文：onkeyup=&quot;value=value.replace(/[W]/g,'') &quot;onbeforepaste=&quot;clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))&quot;<br /><br />如何用正则表达式来表示中文<br /><br />由于中文的ASCII码是有一定的范围的。所以你可以用下面的正则表达式来表示中文。<br /><br />/^[chr(0xa1)-chr(0xff)]+$/<br /><br />下面是一个使用的例子：<br /><br />$str = &quot;超越PHP&quot;;<br />if (preg_match(&quot;/^[&quot;.chr(0xa1).&quot;-&quot;.chr(0xff).&quot;]+$/&quot;, $str)) {<br />echo &quot;这是一个纯中文字符串&quot;;<br />} else {<br />echo &quot;这不是一个纯中文字串&quot;;<br />}<br /><br />正则表达式<br />如果原来没有使用过正则表达式，那么可能对这个术语和概念会不太熟悉。不过，它们并不是您想象的那么新奇。<br /><br />请回想一下在硬盘上是如何查找文件的。您肯定会使用 ? 和 * 字符来帮助查找您正寻找的文件。? 字符匹配文件名中的单个字符，而 * 则匹配一个或多个字符。一个如 'data?.dat' 的模式可以找到下述文件：<br /><br />data1.dat<br /><br />data2.dat<br /><br />datax.dat<br /><br />dataN.dat<br /><br />如果使用 * 字符代替 ? 字符，则将扩大找到的文件数量。'data*.dat' 可以匹配下述所有文件名：<br /><br />data.dat<br /><br />data1.dat<br /><br />data2.dat<br /><br />data12.dat<br /><br />datax.dat<br /><br />dataXYZ.dat<br /><br />尽管这种搜索文件的方法肯定很有用，但也十分有限。? 和 * 通配符的有限能力可以使你对正则表达式能做什么有一个概念，不过正则表达式的功能更强大，也更灵活。<br /><br />--------------------------------------------------------------------------------<br />2<br />早期起源<br />正则表达式的&ldquo;祖先&rdquo;可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。<br /><br />1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上，发表了一篇标题为&ldquo;神经网事件的表示法&rdquo;的论文，引入了正则表达式的概念。正则表达式就是用来描述他称为&ldquo;正则集的代数&rdquo;的表达式，因 此采用&ldquo;正则表达式&rdquo;这个术语。 <br /><br />随后，发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究，Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的qed 编辑器。<br /><br />如他们所说，剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。<br /><br />--------------------------------------------------------------------------------<br />3.<br />使用正则表达式<br />在典型的搜索和替换操作中，必须提供要查找的确切文字。这种技术对于静态文本中的简单搜索和替换任务可能足够了，但是由于它缺乏灵活性，因此在搜索动态文本时就有困难了，甚至是不可能的。 <br /><br />使用正则表达式，就可以： <br /><br />测试字符串的某个模式。例如，可以对一个输入字符串进行测试，看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。 <br />替换文本。可以在文档中使用一个正则表达式来标识特定文字，然后可以全部将其删除，或者替换为别的文字。 <br />根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。 <br />例如，如果需要搜索整个 web 站点来删除某些过时的材料并替换某些HTML 格式化标记，则可以使用正则表达式对每个文件进行测试，看在该文件中是否存在所要查找的材料或 HTML 格式化标记。用这个方法，就可以将受影响的文件范围缩小到包含要删除或更改的材料的那些文件。然后可以使用正则表达式来删除过时的材料，最后，可以再次使 用正则表达式来查找并替换那些需要替换的标记。<br /><br />另一个说明正则表达式非常有用的示例是一种其字符串处理能力还不为人所知的语言。VBScript 是 Visual Basic 的一个子集，具有丰富的字符串处理功能。与 C 类似的 Visual Basic Scripting Edition 则没有这一能力。正则表达式给 Visual Basic Scripting Edition 的字符串处理能力带来了明显改善。不过，可能还是在 VBScript 中使用正则表达式的效率更高，它允许在单个表达式中执行多个字符串操作。<br /><br />--------------------------------------------------------------------------------<br />正则表达式语法<br />一个正则表达式就是由普通字符（例如字符 a 到 z）以及特殊字符（称为元字符）组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板，将某个字符模式与所搜索的字符串进行匹配。<br /><br />这里有一些可能会遇到的正则表达式示例：<br /><br />Visual Basic Scripting Edition VBScript 匹配 <br />/^[ t]*$/ &quot;^[ t]*$&quot; 匹配一个空白行。 <br />/d{2}-d{5}/ &quot;d{2}-d{5}&quot; 验证一个ID 号码是否由一个2位数字，一个连字符以及一个5位数字组成。 <br />/&lt;(.*)&gt;.*&lt;/1&gt;/ &quot;&lt;(.*)&gt;.*&lt;/1&gt;&quot; 匹配一个 HTML 标记。 <br /><br /><br />下表是元字符及其在正则表达式上下文中的行为的一个完整列表：<br /><br />字符 描述 <br />将下一个字符标记为一个特殊字符、或一个原义字符、或一个 后向引用、或一个八进制转义符。例如，'n' 匹配字符 &quot;n&quot;。'n' 匹配一个换行符。序列 '' 匹配 &quot;&quot; 而 &quot;(&quot; 则匹配 &quot;(&quot;。 <br />^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性，^ 也匹配 'n' 或 'r' 之后的位置。 <br />$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性，$ 也匹配 'n' 或 'r' 之前的位置。 <br />* 匹配前面的子表达式零次或多次。例如，zo* 能匹配 &quot;z&quot; 以及 &quot;zoo&quot;。 * 等价于{0,}。 <br />+ 匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 &quot;zo&quot; 以及 &quot;zoo&quot;，但不能匹配 &quot;z&quot;。+ 等价于 {1,}。 <br />? 匹配前面的子表达式零次或一次。例如，&quot;do(es)?&quot; 可以匹配 &quot;do&quot; 或 &quot;does&quot; 中的&quot;do&quot; 。? 等价于 {0,1}。 <br />{n} n 是一个非负整数。匹配确定的 n 次。例如，'o{2}' 不能匹配 &quot;Bob&quot; 中的 'o'，但是能匹配 &quot;food&quot; 中的两个 o。 <br />{n,} n 是一个非负整数。至少匹配n 次。例如，'o{2,}' 不能匹配 &quot;Bob&quot; 中的 'o'，但能匹配 &quot;foooood&quot; 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 <br />{n,m} m 和 n 均为非负整数，其中n &lt;= m。最少匹配 n 次且最多匹配 m 次。刘， &quot;o{1,3}&quot; 将匹配 &quot;fooooood&quot; 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 <br />? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时，匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串，而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如，对于字符串 &quot;oooo&quot;，'o+?' 将匹配单个 &quot;o&quot;，而 'o+' 将匹配所有 'o'。 <br />. 匹配除 &quot;n&quot; 之外的任何单个字符。要匹配包括 'n' 在内的任何字符，请使用象 '[.n]' 的模式。 <br />(pattern) 匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到，在VBScript 中使用 SubMatches 集合，在Visual Basic Scripting Edition 中则使用 $0&hellip;$9 属性。要匹配圆括号字符，请使用 '(' 或 ')'。 <br />(?:pattern) 匹配 pattern 但不获取匹配结果，也就是说这是一个非获取匹配，不进行存储供以后使用。这在使用 &quot;或&quot; 字符 (&#124;) 来组合一个模式的各个部分是很有用。例如， 'industr(?:y&#124;ies) 就是一个比 'industry&#124;industries' 更简略的表达式。 <br />(?=pattern) 正向预查，在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如， 'Windows (?=95&#124;98&#124;NT&#124;2000)' 能匹配 &quot;Windows 2000&quot; 中的 &quot;Windows&quot; ，但不能匹配 &quot;Windows 3.1&quot; 中的 &quot;Windows&quot;。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始。 <br />(?!pattern) 负向预查，在任何不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如'Windows (?!95&#124;98&#124;NT&#124;2000)' 能匹配 &quot;Windows 3.1&quot; 中的 &quot;Windows&quot;，但不能匹配 &quot;Windows 2000&quot; 中的 &quot;Windows&quot;。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始&nbsp;&nbsp;<br />x&#124;y 匹配 x 或 y。例如，'z&#124;food' 能匹配 &quot;z&quot; 或 &quot;food&quot;。'(z&#124;f)ood' 则匹配 &quot;zood&quot; 或 &quot;food&quot;。&nbsp;&nbsp;<br />[xyz] 字符集合。匹配所包含的任意一个字符。例如， '[abc]' 可以匹配 &quot;plain&quot; 中的 'a'。&nbsp;&nbsp;<br />[^xyz] 负值字符集合。匹配未包含的任意字符。例如， '[^abc]' 可以匹配 &quot;plain&quot; 中的'p'。&nbsp;&nbsp;<br />[a-z] 字符范围。匹配指定范围内的任意字符。例如，'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。&nbsp;&nbsp;<br />[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如，'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。&nbsp;&nbsp;<br />b 匹配一个单词边界，也就是指单词和空格间的位置。例如， 'erb' 可以匹配&quot;never&quot; 中的 'er'，但不能匹配 &quot;verb&quot; 中的 'er'。&nbsp;&nbsp;<br />B 匹配非单词边界。'erB' 能匹配 &quot;verb&quot; 中的 'er'，但不能匹配 &quot;never&quot; 中的 'er'。 <br />cx 匹配由x指明的控制字符。例如， cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一个原义的 'c' 字符。&nbsp;&nbsp;<br />d 匹配一个数字字符。等价于 [0-9]。&nbsp;&nbsp;<br />D 匹配一个非数字字符。等价于 [^0-9]。&nbsp;&nbsp;<br />f 匹配一个换页符。等价于 x0c 和 cL。 <br />n 匹配一个换行符。等价于 x0a 和 cJ。 <br />r 匹配一个回车符。等价于 x0d 和 cM。 <br />s 匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [ fnrtv]。 <br />S 匹配任何非空白字符。等价于 [^ fnrtv]。 <br />t 匹配一个制表符。等价于 x09 和 cI。 <br />v 匹配一个垂直制表符。等价于 x0b 和 cK。 <br />w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。&nbsp;&nbsp;<br />W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。&nbsp;&nbsp;<br />xn 匹配 n，其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如， 'x41' 匹配 &quot;A&quot;。'x041' 则等价于 'x04' &amp; &quot;1&quot;。正则表达式中可以使用 ASCII 编码。. <br />num 匹配 num，其中 num 是一个正整数。对所获取的匹配的引用。例如，'(.)1' 匹配两个连续的相同字符。&nbsp;&nbsp;<br />n 标识一个八进制转义值或一个后向引用。如果 n 之前至少 n 个获取的子表达式，则 n 为后向引用。否则，如果 n 为八进制数字 (0-7)，则 n 为一个八进制转义值。 <br />nm 标识一个八进制转义值或一个后向引用。如果 nm 之前至少有is preceded by at least nm 个获取得子表达式，则 nm 为后向引用。如果 nm 之前至少有 n 个获取，则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足，若&nbsp;&nbsp;n 和 m 均为八进制数字 (0-7)，则 nm 将匹配八进制转义值 nm。 <br />nml 如果 n 为八进制数字 (0-3)，且 m 和 l 均为八进制数字 (0-7)，则匹配八进制转义值 nml。 <br />un 匹配 n，其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如， u00A9 匹配版权符号 (?)。<br />4.<br />建立正则表达式<br />构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。 <br /><br />可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式。对 Visual Basic Scripting Edition 而言，分隔符为一对正斜杠 (/) 字符。例如：<br /><br />/expression/<br />对 VBScript 而言，则采用一对引号 (&quot;&quot;) 来确定正则表达式的边界。例如：<br /><br />&quot;expression&quot;<br />在上面所示的两个示例中，正则表达式模式 (expression) 均存储在RegExp 对象的Pattern 属性中。<br /><br />正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。<br /><br />--------------------------------------------------------------------------------<br />5.<br />优先权顺序<br />在构造正则表达式之后，就可以象数学表达式一样来求值，也就是说，可以从左至右并按照一个优先权顺序来求值。 <br /><br />下表从最高优先级到最低优先级列出各种正则表达式操作符的优先权顺序：<br /><br />操作符 描述 <br />转义符 <br />(), (?, (?=), [] 圆括号和方括号 <br />*, +, ?, {n}, {n,}, {n,m} 限定符 <br />^, $, anymetacharacter 位置和顺序 <br />&#124; &ldquo;或&rdquo;操作 <br /><br />--------------------------------------------------------------------------------<br />6.<br />普通字符<br />普通字符由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符，所有数字，所有标点符号以及一些符号。 <br /><br />最简单的正则表达式是一个单独的普通字符，可以匹配所搜索字符串中的该字符本身。例如，单字符模式 'A' 可以匹配所搜索字符串中任何位置出现的字母 'A'。这里有一些单字符正则表达式模式的示例：<br /><br />/a/<br />/7/<br />/M/<br />等价的 VBScript 单字符正则表达式为：<br /><br />&quot;a&quot;<br />&quot;7&quot;<br />&quot;M&quot;<br />可以将多个单字符组合在一起得到一个较大的表达式。例如，下面的 Visual Basic Scripting Edition 正则表达式不是别的，就是通过组合单字符表达式 'a'、'7'以及 'M' 所创建出来的一个表达式。 <br /><br />/a7M/<br />等价的 VBScript 表达式为：<br /><br />&quot;a7M&quot;<br />请注意这里没有连接操作符。所需要做的就是将一个字符放在了另一个字符后面。<br /><br />--------------------------------------------------------------------------------<br />特殊字符<br />有不少元字符在试图对其进行匹配时需要进行特殊的处理。要匹配这些特殊字符，必须首先将这些字符转义，也就是在前面使用一个反斜杠 ()。下表给出了这些特殊字符及其含义：<br /><br />特殊字符 说明 <br />$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性，则 $ 也匹配 'n' 或 'r'。要匹配 $ 字符本身，请使用 $。 <br />( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符，请使用 ( 和 )。 <br />* 匹配前面的子表达式零次或多次。要匹配 * 字符，请使用 *。 <br />+ 匹配前面的子表达式一次或多次。要匹配 + 字符，请使用 +。 <br />. 匹配除换行符 n之外的任何单字符。要匹配 .，请使用 。 <br />[&nbsp;&nbsp;标记一个中括号表达式的开始。要匹配 [，请使用 [。&nbsp;&nbsp;<br />? 匹配前面的子表达式零次或一次，或指明一个非贪婪限定符。要匹配 ? 字符，请使用 ?。 <br />将下一个字符标记为或特殊字符、或原义字符、或后向引用、或八进制转义符。例如， 'n' 匹配字符 'n'。'n' 匹配换行符。序列 '' 匹配 &quot;&quot;，而 '(' 则匹配 &quot;(&quot;。 <br />^ 匹配输入字符串的开始位置，除非在方括号表达式中使用，此时它表示不接受该字符集合。要匹配 ^ 字符本身，请使用 ^。 <br />{ 标记限定符表达式的开始。要匹配 {，请使用 {。 <br />&#124; 指明两项之间的一个选择。要匹配 &#124;，请使用 &#124;。 <br /><br />--------------------------------------------------------------------------------<br />7.<br />非打印字符<br />有不少很有用的非打印字符，偶尔必须使用。下表显示了用来表示这些非打印字符的转义序列：<br /><br />字符 含义 <br />cx 匹配由x指明的控制字符。例如， cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一个原义的 'c' 字符。 <br />f 匹配一个换页符。等价于 x0c 和 cL。 <br />n 匹配一个换行符。等价于 x0a 和 cJ。 <br />r 匹配一个回车符。等价于 x0d 和 cM。 <br />s 匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [ fnrtv]。 <br />S 匹配任何非空白字符。等价于 [^ fnrtv]。 <br />t 匹配一个制表符。等价于 x09 和 cI。 <br />v 匹配一个垂直制表符。等价于 x0b 和 cK。 <br /><br />--------------------------------------------------------------------------------<br />8.<br />字符匹配<br />句点 (.) 匹配一个字符串中任何单个的打印或非打印字符，除了换行符 (n) 之外。下面的 Visual Basic Scripting Edition 正则表达式可以匹配 'aac'、'abc'、'acc'、'adc'如此等等，同样也可以匹配 'a1c'、'a2c'、a-c'以及 a#c'： <br /><br />/a.c/<br />等价的 VBScript 正则表达式为：<br /><br />&quot;a.c&quot;<br />如果试图匹配一个包含文件名的字符串，其中句点 (.) 是输入字符串的一部分，则可以在正则表达式中的句点前面加上一个反斜杠 () 字符来实现这一要求。举例来说，下面的 Visual Basic Scripting Edition 正则表达式就能匹配 'filename.ext'：<br /><br />/filename.ext/<br />对 VBScript 而言，等价的表达式如下所示：<br /><br />&quot;filename.ext&quot;<br />这些表达式仍然是相当有限的。它们只允许匹配任何单字符。很多情况下，对从列表中匹配特殊字符十分有用。例如，如果输入文字中包含用数字表示为Chapter 1, Chapter 2诸如此类的章节标题，你可能需要找到这些章节标题。 <br /><br />括号表达式<br />可以在一个方括号 ([ 和 ]) 中放入一个或多个单字符，来创建一个待匹配的列表。如果字符被放入括号中括起来，则该列表称为括号表达式。括号内和其他任何地方一样，普通字符代表其本 身，也就是说，它们匹配输入文字中出现的一处自己。大多数特殊字符在位于括号表达式中时都将失去其含义。这里有一些例外： <br /><br />']' 字符如果不是第一项，则将结束一个列表。要在列表中匹配 ']' 字符，请将其放在第一项，紧跟在开始的 '[' 后面。 <br />'' 仍然作为转义符。要匹配 '' 字符，请使用 ''。 <br />括号表达式中所包含的字符只匹配该括号表达式在正则表达式中所处位置的一个单字符。下面的 Visual Basic Scripting Edition 正则表达式可以匹配 'Chapter 1'、'Chapter 2'、'Chapter 3'、'Chapter 4' 以及 'Chapter 5'：<br /><br />/Chapter [12345]/<br />在 VBScript 中要匹配同样的章节标题，请使用下面的表达式：<br /><br />&quot;Chapter [12345]&quot;<br />请注意单词 'Chapter' 及后面的空格与括号内的字符的位置关系是固定的。因此，括号表达式只用来指定满足紧跟在单词 'Chapter' 和一个空格之后的单字符位置的字符集合。这里是第九个字符位置。<br /><br />如果希望使用范围而不是字符本身来表示待匹配的字符，则可以使用连字符将该范围的开始和结束字符分开。每个字符的字符值将决定其在一个范围内的相对顺序。 下面的 Visual Basic Scripting Edition 正则表达式包含了一个等价于上面所示的括号列表的范围表达式。<br /><br />/Chapter [1-5]/<br />VBScipt 中相同功能的表达式如下所示：<br /><br />&quot;Chapter [1-5]&quot;<br />如果以这种方式指定范围，则开始和结束值都包括在该范围内。有一点特别需要注意的是，在 Unicode 排序中起始值一定要在结束值之前。<br /><br />如果想在括号表达式中包括连字符，则必须使用下述方法之一： <br /><br />使用反斜杠将其转义： <br />[-]<br />将连字符放在括号列表的开始和结束位置。下面的表达式能匹配所有的小写字母和连字符： <br />[-a-z]<br />[a-z-]<br />创建一个范围，其中开始字符的值小于连字符，而结束字符的值等于或大于连字符。下面两个正则表达式都满足这一要求： <br />[!--]<br />[!-~]<br />同样，通过在列表开始处放置一个插入符(^)，就可以查找所有不在列表或范围中的字符。如果该插入符出现在列表的其他位置，则匹配其本身，没有任何特殊含 义。下面的 Visual Basic Scripting Edition 正则表达式匹配章节号大于 5 的章节标题：<br /><br />/Chapter [^12345]/<br />对 VBScript 则使用：<br /><br />&quot;Chapter [^12345]&quot;<br />在上面所示的示例中，表达式将匹配第九个位置处除1, 2, 3, 4, or 5 之外的任何数字字符。因此， 'Chapter 7' 为一个匹配，同样 'Chapter 9' 也是如此。 <br /><br />上面的表达式可以使用连字符 (-) 表示。对 Visual Basic Scripting Edition 为：<br /><br />/Chapter [^1-5]/<br />或者，对 VBScript 为：<br /><br />&quot;Chapter [^1-5]&quot;<br />括号表达式的典型用法是指定对任何大写或小写字母字符或任何数字的匹配。下面的 Visual Basic Scripting Edition 表达式给出了这一匹配：<br /><br />/[A-Za-z0-9]/<br />等价的 VBScript 表达式为：<br /><br />&quot;[A-Za-z0-9]&quot;<br />9.<br />限定符<br />有时候不知道要匹配多少字符。为了能适应这种不确定性，正则表达式支持限定符的概念。这些限定符可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。<br /><br />下表给出了各种限定符及其含义的说明：<br /><br />字符 描述 <br />*&nbsp;&nbsp;匹配前面的子表达式零次或多次。例如，zo* 能匹配 &quot;z&quot; 以及 &quot;zoo&quot;。 * 等价于{0,}。 <br />+&nbsp;&nbsp;匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 &quot;zo&quot; 以及 &quot;zoo&quot;，但不能匹配 &quot;z&quot;。+ 等价于 {1,}。 <br />?&nbsp;&nbsp;匹配前面的子表达式零次或一次。例如，&quot;do(es)?&quot; 可以匹配 &quot;do&quot; 或 &quot;does&quot; 中的&quot;do&quot; 。? 等价于 {0,1}。 <br />{n} n 是一个非负整数。匹配确定的 n 次。例如，'o{2}' 不能匹配 &quot;Bob&quot; 中的 'o'，但是能匹配 &quot;food&quot; 中的两个 o。 <br />{n,}&nbsp;&nbsp;n 是一个非负整数。至少匹配n 次。例如，'o{2,}' 不能匹配 &quot;Bob&quot; 中的 'o'，但能匹配 &quot;foooood&quot; 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 <br />{n,m}&nbsp;&nbsp;m 和 n 均为非负整数，其中n &lt;= m。最少匹配 n 次且最多匹配 m 次。刘， &quot;o{1,3}&quot; 将匹配 &quot;fooooood&quot; 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 <br /><br /><br />对一个很大的输入文档而言，章节数很轻易就超过九章，因此需要有一种方法来处理两位数或者三位数的章节号。限定符就提供了这个功能。下面的Visual Basic Scripting Edition 正则表达式可以匹配具有任何位数的章节标题：<br /><br />/Chapter [1-9][0-9]*/<br />下面的 VBScript 正则表达式执行同样的匹配：<br /><br />&quot;Chapter [1-9][0-9]*&quot;<br />请注意限定符出现在范围表达式之后。因此，它将应用于所包含的整个范围表达式，在本例中，只指定了从 0 到 9 的数字。<br /><br />这里没有使用 '+' 限定符，因为第二位或后续位置上并不一定需要一个数字。同样也没有使用 '?' 字符，因为这将把章节数限制为只有两位数字。在 'Chapter' 和空格字符之后至少要匹配一个数字。<br /><br />如果已知章节数限制只有99 章，则可以使用下面的 Visual Basic Scripting Edition 表达式来指定至少有一位数字，但不超过两个数字。<br /><br />/Chapter [0-9]{1,2}/<br />对 VBScript 可以使用下述正则表达式：<br /><br />&quot;Chapter [0-9]{1,2}&quot;<br />上述表达式的缺点是如果有一个章节号大于 99，它仍只会匹配前两位数字。另一个缺点是某些人可以创建一个 Chapter 0，而且仍能匹配。一个更好的用来匹配两位数的 Visual Basic Scripting Edition 表达式如下：<br /><br />/Chapter [1-9][0-9]?/<br />或者<br /><br />/Chapter [1-9][0-9]{0,1}/<br />对 VBScript 而言，下述表达式与上面等价：<br /><br />&quot;Chapter [1-9][0-9]?&quot;<br />或者<br /><br />&quot;Chapter [1-9][0-9]{0,1}&quot;<br />'*'、 '+'和 '?' 限定符都称之为贪婪的，也就是说，他们尽可能多地匹配文字。有时这根本就不是所希望发生的情况。有时则正好希望最小匹配。 <br /><br />例如，你可能要搜索一个 HTML 文档来查找一处包含在 H1 标记中的章节标题。在文档中该文字可能具有如下形式：<br /><br />&lt;H1&gt;Chapter 1 &ndash; Introduction to Regular Expressions&lt;/H1&gt;<br />下面的表达式匹配从开始的小于号 (&lt;) 到 H1 标记结束处的大于号之间的所有内容。<br /><br />/&lt;.*&gt;/<br />VBScript 的正则表达式为：<br /><br />&quot;&lt;.*&gt;&quot;<br />如果所要匹配的就是开始的 H1 标记，则下述非贪婪地表达式就只匹配 &lt;H1&gt;。<br /><br />/&lt;.*?&gt;/<br />或者<br /><br />&quot;&lt;.*?&gt;&quot;<br />通过在 '*'、 '+' 或 '?' 限定符后放置 '?'，该表达式就从贪婪匹配转为了非贪婪或最小匹配。<br /><br />10..<br />定位符<br />到现在为止，所看到的示例都只考虑查找任何地方出现的章节标题。出现的任何一个字符串 'Chapter' 后跟一个空格和一个数字可能是一个真正的章节标题，也可能是对其他章节的交叉引用。由于真正的章节标题总是出现在一行的开始，因此需要设计一个方法只查找 标题而不查找交叉引用。<br /><br />定位符提供了这个功能。定位符可以将一个正则表达式固定在一行的开始或结束。也可以创建只在单词内或只在单词的开始或结尾处出现的正则表达式。下表包含了正则表达式及其含义的列表：<br /><br />字符 描述 <br />^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性，^ 也匹配 'n' 或 'r' 之后的位置。 <br />$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性，$ 也匹配 'n' 或 'r' 之前的位置。 <br />b 匹配一个单词边界，也就是指单词和空格间的位置。 <br />B 匹配非单词边界。 <br /><br /><br />不能对定位符使用限定符。因为在一个换行符或者单词边界的前面或后面不会有连续多个位置，因此诸如 '^*' 的表达式是不允许的。<br /><br />要匹配一行文字开始位置的文字，请在正则表达式的开始处使用 '^' 字符。不要把 '^' 的这个语法与其在括号表达式中的语法弄混。它们的语法根本不同。 <br /><br />要匹配一行文字结束位置的文字，请在正则表达式的结束处使用 '$' 字符。<br /><br />要在查找章节标题时使用定位符，下面的 Visual Basic Scripting Edition 正则表达式将匹配位于一行的开始处最多有两个数字的章节标题：<br /><br />/^Chapter [1-9][0-9]{0,1}/<br />VBScript 中相同功能的正则表达式如下：<br /><br />&quot;^Chapter [1-9][0-9]{0,1}&quot;<br />一个真正的章节标题不仅出现在一行的开始，而且这一行中也仅有这一个内容，因此，它必然也位于一行的结束。下面的表达式确保所指定的匹配只匹配章节而不会匹配交叉引用。它是通过创建一个只匹配一行文字的开始和结束位置的正则表达式来实现的。<br /><br />/^Chapter [1-9][0-9]{0,1}$/<br />对 VBScript 则使用：<br /><br />&quot;^Chapter [1-9][0-9]{0,1}$&quot;<br />匹配单词边界有少许不同，但却给正则表达式增加了一个非常重要的功能。单词边界就是单词和空格之间的位置。非单词边界就是其他任何位置。下面的 Visual Basic Scripting Edition 表达式将匹配单词 'Chapter' 的前三个字符，因为它们出现在单词边界后：<br /><br />/bCha/<br />对 VBScript 为：<br /><br />&quot;bCha&quot;<br />这里 'b' 操作符的位置很关键。如果它位于要匹配的字符串的开始，则将查找位于单词开头处的匹配；如果它位于改字符串的末尾，则查找位于单词结束处的匹配。例如，下面的表达式将匹配单词 'Chapter' 中的 'ter'，因为它出现在单词边界之前：<br /><br />/terb/<br />以及<br /><br />&quot;terb&quot;<br />下面的表达式将匹配 'apt'，因为它位于 'Chapter' 中间，但不会匹配 'aptitude' 中的'apt'：<br /><br />/Bapt/<br />以及<br /><br />&quot;Bapt&quot;<br />这是因为在单词 'Chapter' 中 'apt' 出现在非单词边界位置，而在单词 'aptitude' 中位于单词边界位置。非单词边界操作符的位置不重要，因为匹配与一个单词的开头或结尾无关。<br />11.<br /><br />选择与编组<br />选择允许使用 '&#124;' 字符来在两个或多个候选项中进行选择。通过扩展章节标题的正则表达式，可以将其扩充为不仅仅适用于章节标题的表达式。不过，这可没有想象的那么直接。在使 用选择时，将匹配'&#124;' 字符每边最可能的表达式。你可能认为下面的 Visual Basic Scripting Edition 和 VBScript 表达式将匹配位于一行的开始和结束位置且后跟一个或两个数字的 'Chapter' 或 'Section'：<br /><br />/^Chapter&#124;Section [1-9][0-9]{0,1}$/<br />&quot;^Chapter&#124;Section [1-9][0-9]{0,1}$&quot;<br />不幸的是，真正的情况是上面所示的正则表达式要么匹配位于一行开始处的单词 'Chapter'，要么匹配一行结束处的后跟任何数字的 'Section'。如果输入字符串为 'Chapter 22'，上面的表达式将只匹配单词 'Chapter'。如果输入字符串为 'Section 22'，则该表达式将匹配 'Section 22'。但这种结果不是我们此处的目的，因此必须有一种办法来使正则表达式对于所要做的更易于响应，而且确实也有这种方法。<br /><br />可以使用圆括号来限制选择的范围，也就是说明确该选择只适用于这两个单词 'Chapter' 和 'Section'。不过，圆括号同样也是难处理的，因为它们也用来创建子表达式，有些内容将在后面关于子表达式的部分介绍。通过采用上面所示的正则表达 式并在适当位置添加圆括号，就可以使该正则表达式既可以匹配 'Chapter 1'，也可以匹配 'Section 3'。 <br /><br />下面的正则表达式使用圆括号将 'Chapter' 和 'Section' 组成一组，所以该表达式才能正确工作。对 Visual Basic Scripting Edition 为：<br /><br />/^(Chapter&#124;Section) [1-9][0-9]{0,1}$/<br />对 VBScript 为：<br /><br />&quot;^(Chapter&#124;Section) [1-9][0-9]{0,1}$&quot;<br />这些表达式工作正确，只是产生了一个有趣的副产品。在 'Chapter&#124;Section' 两边放置圆括号建立了适当的编组，但也导致两个待匹配单词之一都被捕获供今后使用。由于在上面所示的表达式中只有一组圆括号，因此只能有一个捕获的 submatch。可以使用 VBScript 的Submatches 集合或者Visual Basic Scripting Edition 中RegExp 对象的 $1-$9 属性来引用这个子匹配。<br /><br />有时捕获一个子匹配是所希望的，有时则是不希望的。在说明所示的示例中，真正想做的就是使用圆括号对单词 'Chapter' 或 'Section' 之间的选择编组。并不希望在后面再引用该匹配。实际上，除非真的是需要捕获子匹配，否则请不要使用。由于不需要花时间和内存来存储那些子匹配，这种正则表 达式的效率将更高。<br /><br />可以在正则表达式模式圆括号内部的前面使用 '?:'来防止存储该匹配供今后使用。对上面所示正则表达式的下述修改提供了免除子匹配存储的相同功能。对 Visual Basic Scripting Edition：<br /><br />/^(?:Chapter&#124;Section) [1-9][0-9]{0,1}$/<br />对 VBScript：<br /><br />&quot;^(?:Chapter&#124;Section) [1-9][0-9]{0,1}$&quot;<br />除了 '?:' 元字符，还有两个非捕获元字符用于称之为预查的匹配。一个为正向预查，用 ?= 表示， 在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串。一个为负向预查，用 '?!' 表示，在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。<br /><br />例如，假定有一个包含引用有 Windows 3.1、Windows 95、Windows 98 以及 Windows NT 的文档。进一步假设需要更新该文档，方法是查找所有对 Windows 95、Windows 98 以及 Windows NT 的引用，并将这些引用更改为 Windows 2000。可以使用下面的 Visual Basic Scripting Edition 正则表达式，这是一个正向预查，来匹配 Windows 95、Windows 98 以及 Windows NT：<br /><br />/Windows(?=95 &#124;98 &#124;NT )/<br />在 VBScript 要进行同样的匹配可以使用下述表达式：<br /><br />&quot;Windows(?=95 &#124;98 &#124;NT )&quot;<br />找到一个匹配后，紧接匹配到的文字（而不包括预查中使用的字符）就开始对下一次匹配的搜索。例如，如果上面所示的表达式匹配到 'Windows 98'，则将从 'Windows' 而不是 '98' 之后继续查找。<br /><br />--------------------------------------------------------------------------------<br />12.<br />后向引用<br />正则表达式一个最重要的特性就是将匹配成功的模式的某部分进行存储供以后使用这一能力。请回想一下，对一个正则表达式模式或部分模式两边添加圆括号将导致 这部分表达式存储到一个临时缓冲区中。可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对这部分正则表达式的保存。<br /><br />所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始，连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 'n' 访问，其中 n 为一个标识特定缓冲区的一位或两位十进制数。 <br /><br />后向引用一个最简单，最有用的应用是提供了确定文字中连续出现两个相同单词的位置的能力。请看下面的句子：<br /><br />Is is the cost of of gasoline going up up?<br />根据所写内容，上面的句子明显存在单词多次重复的问题。如果能有一种方法无需查找每个单词的重复现象就能修改该句子就好了。下面的 Visual Basic Scripting Edition 正则表达式使用一个子表达式就可以实现这一功能。 <br /><br />/b([a-z]+) 1b/gi<br />等价的 VBScript 表达式为：<br /><br />&quot;b([a-z]+) 1b&quot;<br />在这个示例中，子表达式就是圆括号之间的每一项。所捕获的表达式包括一个或多个字母字符，即由'[a-z]+' 所指定的。该正则表达式的第二部分是对前面所捕获的子匹配的引用，也就是由附加表达式所匹配的第二次出现的单词。'1'用来指定第一个子匹配。单词边界元 字符确保只检测单独的单词。如果不这样，则诸如 &quot;is issued&quot; 或 &quot;this is&quot; 这样的短语都会被该表达式不正确地识别。 <br /><br />在 Visual Basic Scripting Edition 表达式中，正则表达式后面的全局标志 ('g') 表示该表达式将用来在输入字符串中查找尽可能多的匹配。大小写敏感性由表达式结束处的大小写敏感性标记 ('i') 指定。多行标记指定可能出现在换行符的两端的潜在匹配。对 VBScript 而言，在表达式中不能设置各种标记，但必须使用 RegExp 对象的属性来显式设置。<br /><br />使用上面所示的正则表达式，下面的 Visual Basic Scripting Edition 代码可以使用子匹配信息，在一个文字字符串中将连续出现两次的相同单词替换为一个相同的单词：<br /><br />var ss = &quot;Is is the cost of of gasoline going up up?.n&quot;;<br />var re = /b([a-z]+) 1b/gim;&nbsp; &nbsp;&nbsp; &nbsp; //创建正则表达式样式.<br />var rv = ss.replace(re,&quot;$1&quot;);&nbsp; &nbsp;//用一个单词替代两个单词.<br />最接近的等价&nbsp;&nbsp;VBScript 代码如下：<br /><br />Dim ss, re, rv<br />ss = &quot;Is is the cost of of gasoline going up up?.&quot; &amp; vbNewLine<br />Set re = New RegExp<br />re.Pattern = &quot;b([a-z]+) 1b&quot;<br />re.Global = True<br />re.IgnoreCase = True<br />re.MultiLine = True<br />rv = re.Replace(ss,&quot;$1&quot;)<br />请注意在 VBScript 代码中，全局、大小写敏感性以及多行标记都是使用 RegExp 对象的适当属性来设置的。<br /><br />在replace 方法中使用 $1 来引用所保存的第一个子匹配。如果有多个子匹配，则可以用 $2, $3 等继续引用。<br /><br />后向引用的另一个用途是将一个通用资源指示符 (URI) 分解为组件部分。假定希望将下述的URI 分解为协议 (ftp, http, etc)，域名地址以及页面/路径：<br /><br /><a href="http://msdn.microsoft.com/scripting/default.htm" target="_blank"><a href="http://msdn.microsoft.com:80/scripting/default.htm" target="_blank">http://msdn.microsoft.com:80/scripting/default.htm</a></a><br />下面的正则表达式可以提供这个功能。对 Visual Basic Scripting Edition，为：<br /><br />/(w+)://([^/:]+)(:d*)?([^# ]*)/<br />对 VBScript 为：<br /><br />&quot;(w+)://([^/:]+)(:d*)?([^# ]*)&quot;<br />第一个附加子表达式是用来捕获该 web 地址的协议部分。该子表达式匹配位于一个冒号和两个正斜杠之前的任何单词。第二个附加子表达式捕获该地址的域名地址。该子表达式匹配不包括 '^'、 '/' 或 ':' 字符的任何字符序列。第三个附加子表达式捕获网站端口号码，如果指定了该端口号。该子表达式匹配后跟一个冒号的零或多个数字。最后，第四个附加子表达式捕 获由该 web 地址指定的路径以及或者页面信息。该子表达式匹配一个和多个除'#' 或空格之外的字符。<br /><span style="font-size: xx-small; color: #c0c0c0">by clin003 from:<a href="http://clin003.com/" target="_blank">http://clin003.com/</a>或<a href="http://blog.csdn.net/cin003/" target="_blank">http://blog.csdn.net/cin003/</a></span><br />将该正则表达式应用于上面所示的 URI 后，子匹配包含下述内容：<br /><br />RegExp.$1 包含 &quot;http&quot;<br /><br />RegExp.$2 包含 &quot;msdn.microsoft.com&quot;<br /><br />RegExp.$3 包含 &quot;:80&quot;<br /><br />RegExp.$4 包含 &quot;/scripting/default.htm&quot;<br /><br />正则表达式广泛出现在UNIX/Linux相关的各种领域和多种编程语言里。从常见的shell命令到大名鼎鼎的Perl语言再到当前非常流行的PHP， 它都扮演着一个重要的角色。甚至windows的命令行控制台也支持正则表达式。如果你是一个Linux服务器管理员，你经常会在一些服务器的设置脚本里 看到它。<br /><br />　　可以说，它是学好Linux/UNIX必需掌握的一个知识点，否则你连Linux的启动脚本都读不懂。偏偏它又的确有点晦涩难懂，而且相关的资料又大 部分是英文，更为它的学习增加了几多困难。即使有些中文的翻译资料，不同的译者对一些术语的译法也五花八门，读着让人平添困惑。为此，我决定为它写一个简 明教程，尽量可以覆盖正则表达式涉及到的各主要概念。<br /><br />　　我并不想把本文写成一本详细的正则表达式语法手册，事实上，这些手册已经存在了，不过读起来比较难懂。我希望的是在完成本教程后，你可以比较轻松的读 懂各种工具的正则表达式语法手册并可以迅速上手，不过要用好正则表达式，可不是一篇短短的教程可以解决的，那是无数实践练习的结果。但是，本文的最后一部 分对于正则表达式的编写提出了一些原则性的建议，学习一下这些正则表达式应用先驱者的经验会让我们在今后的实践中少走一些弯路。<br /><br />　　正则表达式是英文&ldquo;regular expressions&rdquo;的译文，它的产生据说可以追溯到&ldquo;神经网络&rdquo;等比较高深的理论。那么什么是正则表达式呢?<br /><br />　　正则表达式是从左向右去匹配目标字符串的一组模式。大多数字符在模式中表示它们自身并匹配目标中相应的字符。举个最简单的例子，模式&ldquo;The quick brown fox&rdquo;匹配了目标字符串中与其完全相同的一部分。<br /><br />　　前面已经提过，正则表达式被许多植根于UNIX/Linux的工具采用，可是这些工具的正则表达式语法并不完全相同，它们中的一些对正则表达式语法的 扩展并不被其它工具识别，这也为正则表达式的使用增加了难度。因此，当你在一个具体的环境中使用正则表达式时，你还要先看一下目标环境支持的语法范围，以 确保你的正则表达式被正确的解析。<br /><br />　　在本文中列举的例子里，我们用正斜线&ldquo;/&rdquo;做为模式的定界符(delimiter)，一个模式用下面这种格式表示:<br /><br />/[A-Z]+(abc&#124;xyz)*/i <br /><br /><br />　　本文将较详细的阐明下面这些正则表达式概念：模式修正符（modifier），元字符（Meta-characters），子模式 （subpatterns）与逆向引用（Back references），重复（Repetition）和量词（quantifiers），断言（Assertions），注释，正则表达式中的递归，最 后我介绍一款方便学习正则表达式的工具并介绍一些正则表达式编写的思路。<br /><br />正则表达式的模式修正符(modifier)<br /><br />　　正则表达式的模式修正符主要用来限定模式与目标字符串的匹配方式，例如是否需要大小写敏感的匹配，是单行模式还是多行模式。修正符中的空格和换行被忽略，其它字符会导致错误。下面列举一些常见的模式修正符。注意，模式修正符是区分大小写的。<br /><br />　　i:非大小写敏感模式，:如果设定此修正符，模式中的字符将同时匹配大小写字母。<br /><br />　　m:多行模式，当设定了此修正符，&ldquo;行起始&rdquo;和&ldquo;行结束&rdquo;除了匹配整个字符串开头和结束外，还分别匹配其中的换行符的之后和之前。<br /><br />　　s:单行模式，如果设定了此修正符，模式中的圆点元字符(.)匹配所有的字符，包括换行符。没有此设定的话，则不包括换行符。<br /><br />　　对于多行模式和单行模式，一个容易让初学者迷惑的地方是这两者并不向字面上那样是互斥的。事实上，它们只是分别定义了英文句点(.)、音调符(^)和美元符($)这三个元字符的匹配方式，因此，单行模式与多行模式的修正符可以同时使用。<br /><br />　　x:如果设定了此修正符，模式中的空白字符除了被转义的或在字符类中的以外完全被忽略，在未转义的字符类之外的 # 以及下一个换行符之间的所有字符，包括两头，也都被忽略。它使得可以在复杂的模式中加入注释。我们会在后面的部分更详细的讲解正则表达中的注释。<br /><br />　　模式修正符还有很多，这里不再一一列举。我们会结合后面的内容介绍一些其它的模式修正符。不同的工具也可以添加自己的模式修正符，不过上面几最为常见。<br /><br />　　模式修正符通常跟在模式定义结束符的后面，例如下面例子中模式最后的&ldquo;i&rdquo;字符。/[A-Z]+(abc&#124;xyz)*/i，这时此修正符会对整个匹配 模式起作用。模式修正符也可以在模式内部通过包含在 &quot;(?&quot; 和 &quot;)&quot; 之间的修正符字母序列来实现。例如，(?im) 设定了不区分大小写，多行模式。也可以通过在字母前加上减号来取消这些选项。例如组合的选项 (?im-s)，设定了不区分大小写和多行模式，并取消了单行模式。如果一个字母在减号之前与之后都出现了，则该选项被取消设定。<br /><br />　　注意，如果(?im-s)出现在一个子模式内(被另一对小括号包含)会把模式修正符的作用局限在该子模式中。<br />正则表达式的元字符（Meta-characters）<br /><br />　　正则表达式的威力在于其能够在模式中包含选择和循环。它们通过使用元字符来编码在模式中，元字符不代表其自身，它们用一些特殊的方式来解析。<br /><br />　　有两组不同的元字符:一种是模式中除了方括号内都能被识别的，还有一种是在方括号内被识别的。如果想在模式里包含一个元字符本身，就需要用到转义符 号，正则表达式常用反斜线&ldquo;&rdquo;作为转义字符使用，为了匹配&ldquo;&rdquo;本身，你需要输入两个&ldquo;&rdquo;，向这样&ldquo;&rdquo;。当然，这个符号本身也是一个元字符。<br /><br />　　方括号之外的元字符有这些:<br /><br />　　<br /><br />　　有数种用途的通用转义符<br /><br />　　^<br /><br />　　断言目标的开头(或在多行模式下行的开头，即紧随一换行符之后)<br /><br />　　$<br /><br />　　断言目标的结尾(或在多行模式下行的结尾，即紧随一换行符之前)<br /><br />　　.<br /><br />　　匹配除了换行符外的任意一个字符(默认情况下)<br /><br />　　[<br /><br />　　字符类定义开始<br /><br />　　]<br /><br />　　字符类定义结束<br /><br />　　&#124;<br /><br />　　开始一个多选一的分支<br /><br />　　(<br /><br />　　子模式开始<br /><br />　　)<br /><br />　　子模式结束<br /><br />　　?<br /><br />　　扩展 ( 的含义，我们已经在介绍模式修正符里看到过它的使用。它也可以是 0 或 1 数量限定符，以及数量限定符最小值<br /><br />　　*<br /><br />　　匹配 0 个或多个的数量限定符<br /><br />　　+<br /><br />　　匹配 1 个或多个的数量限定符<br /><br />　　{<br /><br />　　最少/最多数量限定开始<br /><br />　　}<br /><br />　　最少/最多数量限定结束<br /><br />　　模式中方括号内的部分称为&ldquo;字符类&rdquo;。字符类中可用的元字符为:<br /><br />　　<br /><br />　　通用转义字符<br /><br />　　^<br /><br />　　排除字符类，但仅当其为第一个字符时有效<br /><br />　　-<br /><br />　　指出字符范围&nbsp;&nbsp;<br />在这里，最值得一提是&ldquo;&rdquo;这个元字符。之所以重点对它进行讲解是因为这一个元字符有多种不同的用法，在不同情况下代表不同的含义，而且使用频率非常高，是个很容易让人迷惑的地方。<br /><br />　　第一种用法前面我们已经提过，是作为通用转义字符使用，如果其后跟着一个非字母数字字符，则取消该字符可能具有的任何特殊含义。此种将反斜线用作转义字符的用法适用于无论是字符类之中还是之外。例如&ldquo;&rdquo;代表一个单独的反斜线&ldquo;&rdquo;。<br /><br />　　第二种用途提供了一种在模式中以可见方式去编码不可打印字符的方法。模式中完全可以包括不可打印字符，除了代表模式结束的二进制零，例如，可以用 &ldquo;a&rdquo;代表alarm，即 BEL 字符(0x07)，或用&ldquo;cx&rdquo;代表&quot;control-x&quot;，其中 x 是任意字符。当然，这种方法表示的不一定非得是不可打印字符，实际上，可以用&ldquo;xhh(十六进制代码为 hh 的字符)&rdquo;和&ldquo;ddd(八进制代码为 ddd 的字符)&rdquo;来以编码的形式表达任何单字节字符，例如&ldquo;�40&rdquo;可以用来表示空格。<br /><br />　　反斜线的第三个用法是指定通用字符类型，这些字符类型序列可以出现在字符类之中和之外。每一个匹配相应类型中的一个字符。如果当前匹配点在目标字符串的结尾，以上所有匹配都失败，因为没有字符可供匹配。有以下这些常见的通用字符类:<br /><br />　　d 任一十进制数字<br /><br />　　D任一非十进制数的字符<br /><br />　　s任一空白字符<br /><br />　　S任一非空白字符<br /><br />　　w任一&ldquo;字&rdquo;的字符<br /><br />　　W任一&ldquo;非字&rdquo;的字符<br /><br />　　反斜线的第四个用法是某些简单的断言，关于断言的讨论我们放在后面，这里先不加讨论。<br /><br />　　反斜线的最后一个用法是逆向引用。关于逆向引用，我们会在后面讨论逆向引用的部分来做进一步的讨论。<br /><br />　　我们已经看到，反斜线的众多用法，其中一些涉及到了以后才讲的内容。我们在模式中遇到反斜线时一定要注意它具体是哪一种用途以免疑惑。<br /><br />　　另外两个方括号也是非常重要的元字符，左方括号开始了一个字符类，右方括号结束之。单独一个右方括号不是特殊字符。字符类匹配目标中的一个字符，该字 符必须是字符类定义的字符集中的一个;除非字符类中的第一个字符是音调符(^)，此情况下目标字符必须不在字符类定义的字符集中。如果在字符类中需要音调 符本身，则其必须不是第一个字符，或用反斜线转义。例如，[^A-Z]表式非大写字符。<br /><br />　　其它元字符我们会在以后的文章中结合相关内容介绍。<br /><br /><br />【导读】在本文里，我们主要介绍子模式(subpatterns)，逆向引用(Back references)和量词(quantifiers)<br /><br />在上篇文章里，我们介绍了正则表达式的模式修正符与元字符，细心的读者也许会发现，这部分介绍的非常简略，而且很少有实际的例子的讲解。这主要是因为网上 现有的正则表达式资料都对这部分都有详细的介绍和众多的例子，如果觉得对前一部分缺乏了解可以参看这些资料。本文希望可以尽可能多涉及一些较高级的正则表 达式特性。<br /><br />　　在本文里，我们主要介绍子模式(subpatterns)，逆向引用(Back references)和量词(quantifiers)，其中重点介绍对这些概念的一些扩展应用，例如子模式中的非捕获子模式，量词匹配时的greedy与ungreedy。<br /><br />　　子模式(subpatterns)与逆向引用(Back references)<br /><br />　　正则表达式可以包含多个字模式，子模式由圆括号定界，可以嵌套。这也是两个元字符&ldquo;(&rdquo;和&ldquo;)&rdquo;的作用。子模式可以有以下作用:<br /><br />　　1. 将多选一的分支局部化。<br /><br />　　例如，模式: cat(aract&#124;erpillar&#124;)匹配了 &quot;cat&quot;，&quot;cataract&quot; 或 &quot;caterpillar&quot; 之一，没有圆括号的话将匹配 &quot;cataract&quot;，&quot;erpillar&quot; 或空字符串。<br /><br />　　2. 将子模式设定为捕获子模式(例如上面这个例子)。当整个模式匹配时，目标字符串中匹配了子模式的部分可以通过逆向引用进行调用。左圆括号从左到右计数(从 1 开始)以取得捕获子模式的数。<br /><br />　　注意，子模式是可以嵌套的，例如，如果将字符串 &quot;the red king&quot; 来和模式 /the ((red&#124;white) (king&#124;queen))/进行匹配，捕获的子串为 &quot;red king&quot;，&quot;red&quot; 以及 &quot;king&quot;，并被计为 1，2 和 3 ，可以通过&ldquo;1&rdquo;，&ldquo;2&rdquo;，&ldquo;3&rdquo;来分别引用它们，&ldquo;1&rdquo;包含了&ldquo;2&rdquo;和&ldquo;3&rdquo;，它们的序号是由左括号的顺序决定的。<br /><br />　　在一些老的linux/unux工具里，子模式使用的圆括号需要用反斜线转义，向这种(subpattern)，但现代的工具已经不需要了，本文中使用的例子都不进行转义。<br /><br /><br />非捕获子模式(non-capturing subpatterns)<br /><br />　　用一对括号同时完成上面提到的子模式的两个功能有时会出现一些问题，例如，由于逆向引用的数目是有限的(通常最大不超过9)，而且经常会遇到无需捕获 的子模式定义。这时，可以在开始的括号后加上问号和冒号来表示这个子模式无需捕获，就向下面这样(?:red&#124;white) (king&#124;queen))。<br /><br />　　如果将&ldquo;the white queen&rdquo;作为模式匹配的目标字符串，则捕获的字串有&ldquo;white queen&rdquo;和&ldquo;queen&rdquo;，分别作为&ldquo;1&rdquo;和&ldquo;2&rdquo;，white虽然符合子模式&ldquo;(?:red&#124;white)&rdquo;，但并不被捕获。<br /><br />　　我们前面已经介绍过用括号与问号表示模式修正符的方法，为方便起见，如果需要在非捕获子模式中插入模式修正符，可以把它直接放在问号和冒号之间，例如，下面两个模式是等效的。<br /><br />　　/(?i:saturday&#124;sunday)/和/(??i)saturday&#124;sunday)/。<br /><br />　　逆向引用(Back references)<br /><br />　　前面介绍反斜线作用时，已经提到它的一个作用就是表示逆向引用，当字符类之外的反斜线后跟一个大于0的十进制数时，它很有可能是一个逆向引用。它的含 义正如它的名称如言，它表示对它出现之前已经捕获的子模式的引用。这个数字代表了它引用的左括号在模式中出现的次序，我们在介绍子模式时已经看到过逆向引 用的一个例子，那里的过&ldquo;1&rdquo;，&ldquo;2&rdquo;，&ldquo;3&rdquo;分别表示所捕获的第一，第二，和第三个小括号定义的子模式的内容。<br /><br />　　值得注意的是，当反斜线后的数字小于10时，可以确定此为一个逆向引用，这样，这个逆向引用就可以出现在之前有相应数目的左圆括号被捕获前而不会出现 混淆，只有整个模式能提供那么多的捕获子模式，就不会报错。说起来似乎很混乱，还是让我们来看下面这个例子。把介绍子模子时举的例子拿来修改一下，前面讲 过字符串 &quot;the red king&quot; 来和模式 /the ((red&#124;white) (king&#124;queen))/匹配，捕获的子串为 &quot;red king&quot;，&quot;red&quot; 以及 &quot;king&quot;，并被计为 1，2 和 3 ，现在把字符串，修改为&quot; king，the red king&quot;，模式改为/3,the ((red&#124;white) (king&#124;queen))/，这个模式应该也是可以匹配的。不过，并非所有的正则表达式工具都支持这种用法，安全的做法是在相应序号的左括号之后使用与 之相关的逆向引用。<br /><br />　　需要注意的另一点是逆向引用的值是在目标字符串中实际捕获的符合子模式的字符串片段而非该子模式本本身。例如/ (sens&#124;respons)e and 1ibility/会匹配&ldquo;sense and sensibility&rdquo; 和 &ldquo;response and responsibility&rdquo;，但不会是 &quot;sense and responsibility&quot;。当被逆向引用的子模式后面有量词从而被重复匹配了多次，逆向引用的值会以最后一次匹配的值为准。例如/([abc]) {3}/匹配字符串&ldquo;abc&rdquo;时，逆向引用&ldquo;1&rdquo;的值将是最后一次匹配的结果&ldquo;c&rdquo;。<br /><br />　　命名子模式(named subpattern)<br /><br />　　一些工具(例如Python)可以为逆向引用命名，从而定义出命名子模式。在Python中对正则表达式的使用是以函数或方法调用的格式，语法与这里举的例子有较大差别。有兴趣的朋友可以参看一下自己使用的工具来看看是否支持命名子模式。<br /><br />非捕获子模式(non-capturing subpatterns)<br /><br />　　用一对括号同时完成上面提到的子模式的两个功能有时会出现一些问题，例如，由于逆向引用的数目是有限的(通常最大不超过9)，而且经常会遇到无需捕获 的子模式定义。这时，可以在开始的括号后加上问号和冒号来表示这个子模式无需捕获，就向下面这样(?:red&#124;white) (king&#124;queen))。<br /><br />　　如果将&ldquo;the white queen&rdquo;作为模式匹配的目标字符串，则捕获的字串有&ldquo;white queen&rdquo;和&ldquo;queen&rdquo;，分别作为&ldquo;1&rdquo;和&ldquo;2&rdquo;，white虽然符合子模式&ldquo;(?:red&#124;white)&rdquo;，但并不被捕获。<br /><br />　　我们前面已经介绍过用括号与问号表示模式修正符的方法，为方便起见，如果需要在非捕获子模式中插入模式修正符，可以把它直接放在问号和冒号之间，例如，下面两个模式是等效的。<br /><br />　　/(?i:saturday&#124;sunday)/和/(?:(?i)saturday&#124;sunday)/。<br /><br />　　逆向引用(Back references)<br /><br />　　前面介绍反斜线作用时，已经提到它的一个作用就是表示逆向引用，当字符类之外的反斜线后跟一个大于0的十进制数时，它很有可能是一个逆向引用。它的含 义正如它的名称如言，它表示对它出现之前已经捕获的子模式的引用。这个数字代表了它引用的左括号在模式中出现的次序，我们在介绍子模式时已经看到过逆向引 用的一个例子，那里的过&ldquo;1&rdquo;，&ldquo;2&rdquo;，&ldquo;3&rdquo;分别表示所捕获的第一，第二，和第三个小括号定义的子模式的内容。<br /><br />　　值得注意的是，当反斜线后的数字小于10时，可以确定此为一个逆向引用，这样，这个逆向引用就可以出现在之前有相应数目的左圆括号被捕获前而不会出现 混淆，只有整个模式能提供那么多的捕获子模式，就不会报错。说起来似乎很混乱，还是让我们来看下面这个例子。把介绍子模子时举的例子拿来修改一下，前面讲 过字符串 &quot;the red king&quot; 来和模式 /the ((red&#124;white) (king&#124;queen))/匹配，捕获的子串为 &quot;red king&quot;，&quot;red&quot; 以及 &quot;king&quot;，并被计为 1，2 和 3 ，现在把字符串，修改为&quot; king，the red king&quot;，模式改为/3,the ((red&#124;white) (king&#124;queen))/，这个模式应该也是可以匹配的。不过，并非所有的正则表达式工具都支持这种用法，安全的做法是在相应序号的左括号之后使用与 之相关的逆向引用。<br /><br />　　需要注意的另一点是逆向引用的值是在目标字符串中实际捕获的符合子模式的字符串片段而非该子模式本本身。例如/ (sens&#124;respons)e and 1ibility/会匹配&ldquo;sense and sensibility&rdquo; 和 &ldquo;response and responsibility&rdquo;，但不会是 &quot;sense and responsibility&quot;。当被逆向引用的子模式后面有量词从而被重复匹配了多次，逆向引用的值会以最后一次匹配的值为准。例如/([abc]) {3}/匹配字符串&ldquo;abc&rdquo;时，逆向引用&ldquo;1&rdquo;的值将是最后一次匹配的结果&ldquo;c&rdquo;。<br /><br />　　命名子模式(named subpattern)<br /><br />　　一些工具(例如Python)可以为逆向引用命名，从而定义出命名子模式。在Python中对正则表达式的使用是以函数或方法调用的格式，语法与这里举的例子有较大差别。有兴趣的朋友可以参看一下自己使用的工具来看看是否支持命名子模式。<br /><br />重复(Repetition)和量词(quantifiers)<br /><br />　　在前面介绍逆向引用的部分里我们已经接触到了量词(quantifiers)的概念，例如前面的例子/([abc]){3}/表示三个连续的字符，每 个字符都必然是 &ldquo;abc&rdquo;这三个字符中的一个。在这个模式里，{3}就属于量词。它表示一个模式需要重复匹配(repetition)的数目。<br /><br />　　量词可以放在下面这些项目之后:<br /><br />　　?●单个字符(有可能是被转义的单个字符，如xhh)<br /><br />　　?●&ldquo;.&rdquo;元字符<br /><br />　　?● 由方括号表示的字符类<br /><br />　　?● 逆向引用<br /><br />　　?●由小括号定义的子模式(除非它是个断言，我们会在以后介绍)<br /><br />　　最通用的量词使用形式是用花括号括起的两个由逗号分隔的数字，如这样的格式{min,max}，例如，/z{2,4}/ 可以匹配 &quot;zz&quot;, &quot;zzz&quot;, 或者 &quot;zzzz&quot;，花括号中的最大值以及前面的逗号可以省略，例如/d{3,}/可以匹配三个以上的数字，数字的数目没有上限，而/d{3}/(注意，没有逗 号)则精确的匹配3个数字。当花括号出现在不允许量词的位置或者语法与前面提到的不符时，这里它仅仅代表花括号字符本身而不再具有特殊的含义。例如{, 6}不是量词，它仅仅代表这四个字符本身的含义。<br /><br />　　为了方便，三个最常用的量词有它们的单字符缩写形式，它们的的含义如下表:<br /><br />* 相当于 {0,} <br />+ 相当于 {1,} <br />? 相当于 {0,1} <br /><br /><br />　　这也是以上三个元字符做为量词使用含义。<br /><br />　　在使用量词特别是没有上限限制的量词时，应该特别注意不要构成无限循环，例如/(a?)*/，在有的正则表达式工具里。这会形成一个编译错，不过有的工具却允许这种结构，但不能保证各种工具都可以很好的处理这种结构。<br /><br />重复(Repetition)和量词(quantifiers)<br /><br />　　在前面介绍逆向引用的部分里我们已经接触到了量词(quantifiers)的概念，例如前面的例子/([abc]){3}/表示三个连续的字符，每 个字符都必然是 &ldquo;abc&rdquo;这三个字符中的一个。在这个模式里，{3}就属于量词。它表示一个模式需要重复匹配(repetition)的数目。<br /><br />　　量词可以放在下面这些项目之后:<br /><br />　　?●单个字符(有可能是被转义的单个字符，如xhh)<br /><br />　　?●&ldquo;.&rdquo;元字符<br /><br />　　?● 由方括号表示的字符类<br /><br />　　?● 逆向引用<br /><br />　　?●由小括号定义的子模式(除非它是个断言，我们会在以后介绍)<br /><br />　　最通用的量词使用形式是用花括号括起的两个由逗号分隔的数字，如这样的格式{min,max}，例如，/z{2,4}/ 可以匹配 &quot;zz&quot;, &quot;zzz&quot;, 或者 &quot;zzzz&quot;，花括号中的最大值以及前面的逗号可以省略，例如/d{3,}/可以匹配三个以上的数字，数字的数目没有上限，而/d{3}/(注意，没有逗 号)则精确的匹配3个数字。当花括号出现在不允许量词的位置或者语法与前面提到的不符时，这里它仅仅代表花括号字符本身而不再具有特殊的含义。例如{, 6}不是量词，它仅仅代表这四个字符本身的含义。<br /><br />　　为了方便，三个最常用的量词有它们的单字符缩写形式，它们的的含义如下表:<br /><br />* 相当于 {0,} <br />+ 相当于 {1,} <br />? 相当于 {0,1} <br /><br /><br />　　这也是以上三个元字符做为量词使用含义。<br /><br />　　在使用量词特别是没有上限限制的量词时，应该特别注意不要构成无限循环，例如/(a?)*/，在有的正则表达式工具里。这会形成一个编译错，不过有的工具却允许这种结构，但不能保证各种工具都可以很好的处理这种结构。<br /><br />量词匹配的&ldquo;greedy&rdquo;与&ldquo;ungreedy&rdquo;<br /><br />　　在使用带量词的模式时，我们常会发现对同一模式而言，同一个目标字符串可以有多种匹配方式。例如/d{0,1}d/，可以匹配两个或三个十进制数字， 如果目标字符串是123，当量词取下限0里，它匹配&ldquo;12&rdquo;，当量词取上限1里，它匹配&ldquo;123&rdquo;整个字符。这两种匹配结果都是正确的，如果我们取它的子 模式/(d{0,1}d)/，则匹配的结果1到底是&ldquo;12&rdquo;还是&ldquo;123&rdquo;?<br /><br />　　实际的运行结果一般会是后者，因为默认情况下，大多数正则表达式工具的匹配是按&ldquo;greedy&rdquo;原则匹配的。&ldquo;greedy&rdquo;单词的中的含义是&ldquo;贪吃 的, 贪婪的&rdquo;的意思，它的行为也如此单词的含义，所谓greedy匹配意指在量词限制范围内，只要能保持后续模式的匹配，匹配总是尽可能的重复下去，直到不匹 配的情况发生为止。为便于理解，我们看下面这个简单的例子。<br /><br />　　/(d{1,5})d/匹配&ldquo;12345&rdquo;这个字符串，这个模式表示在1到5个数字后面跟上一个数字，量词范围从1到5，当它的值在1-4时，整个模 式都是匹配的，1的值可以是&ldquo;1&rdquo;，&ldquo;12&rdquo;，&ldquo;123&rdquo;，&ldquo;1234&rdquo;，而在greedy匹配的情况下，它取匹配时的量词最大值，因此最终匹配的结果 是&rdquo;1234&rdquo;。<br /><br />　　在大多数情况下，这就是我们想要的结果，但情况并不总这样。例如，我们希望用下面这个模式提取出c语言的注释部分(在c语言中，注释语句放在字符串 /*和*/之间)。我们使用的正则表达式是/*.**/，但匹配的结果却完全和需要的不同。当正则表达式解析到&ldquo;/*&rdquo;这后的&ldquo;.*&rdquo;时，因为&ldquo;.&rdquo;可以 代表任意字符，这也包含了其后需要匹配的&ldquo;*/&rdquo;，在量词的作用下，这个匹配将一直进行下去，超过下一个&ldquo;*&rdquo;/直到文本的结束，这显然不是我们需要的结 果。<br /><br />　　为了完成如上例我们想要的那种匹配，正则表达式引入了ungreedy匹配方法，与greedy匹配相反，在满足整个模式匹配的前提下，它总是取最小 的量词数目结果。Ungreedy匹配用在量词后面加上问号&ldquo;?&rdquo;来表示。例如在匹配C语言的注释时，我们把正则表达式写成如下形式:/*.*?*/，在 量词&ldquo;*&rdquo;后加上问号就可以达成想要的结果。还有前面那个例子用/(d{1,5})d/匹配&ldquo;12345&rdquo;这个字符串，如果改写为ungreedy模式向 这样/(d{1,5}?)d/，、1的值将为1。<br /><br />　　上面的解释也许有些不准确，量词后的问号的作用实际上是反转当前的正则表达式的greedy与ungreedy行为。你可以通过模式修正符&ldquo;U&rdquo;将正则表达式设成ungreedy模式然后在模式中通过量词后的问号将之反转为greedy。<br /><br />　　一次性子模式(Once-only subpatterns)<br /><br />　　关于量词的另一个有趣的话题是一次性子模式(Once-only subpatterns)。要理解它的概念需要先了解一下含有量词的正则表达式的匹配过程。我们这里举个例子。<br /><br />　　现在，让我们用模式/d+foo/来匹配字符串&ldquo;123456bar&rdquo;，当然，它的结果是没有匹配。但正则表达式引擎是如何工作的呢?它先分析前面的 d+，这代表一个以上的数字，然后检查目标字符串的对应位置的第一个字符&ldquo;1&rdquo;，符合模式，然后根据量词重复这个模式对字符串进行匹配直到 &ldquo;123456&rdquo;始终符合&ldquo;d+&rdquo;模式，接着它在目标字符串中遇到字符&ldquo;b&rdquo;无法与&ldquo;d+&rdquo;匹配，于是查看&ldquo;d+&rdquo;的后续模式&ldquo;foo&rdquo;，与目标字符串的 后续部分&ldquo;bar&rdquo;无法匹配，这时，有趣的事情出现了，解释引擎会对前面已经解析过的&ldquo;d+&rdquo;模式进行回溯，将量词数目减少一，看剩余部分能否匹配，此时 &ldquo;d+&rdquo;的值改为&ldquo;12345&rdquo;，然后解释引擎看目标字符串剩余的部分&ldquo;6bar&rdquo;能否与剩余的模式&ldquo;foo&rdquo;相匹配，如果不行，就把量词数再减一，直到 达到最小的量词限制，如果仍无法匹配，则表明目标字符串无法匹配，返回无法匹配的结果。<br /><br />　　现在，我们就可以来接触一次性子模式了。所谓一次性子模式就是定义在正则表达式解析时不需要上述回溯过程的子模式。它用左圆括号后面的问号和小于号来表示，向这样(?&gt;)。如果将上面提到的例子改为一次性子模式，可以这样书写:<br /><br />　　/(?&gt;d)+foo/，这时，当解析器遇到后面不匹配的bar时，会立即返回不匹配的结果，而不会进行前面提到的回溯过程。<br /><br />　　需要了解的是，一次性子模式属于非捕获子模式，它的匹配结果不能被逆向引用。<br /><br />　　当一个没有设定重复上限的子模式中包含了同样没有设定重复上限的模式时，使用一次性子模式是唯一可以避免让你的程序陷入长时间等待的方法。例如你用 &ldquo;/(D+&#124;&lt;d+&gt;)*[!?]/&rdquo;这个模式去匹配一长串的a字符，向这样 &ldquo;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&rdquo;，在返回最终无匹配的结果前，你会等待很长的一段时间。这个模式表示一串非数字 字符或者用尖括号括着的一串数字后跟随着叹号或者问号，把这段字符串分成两个重复的部分会有很多种分法，而无论是子模式本身还是子模式之内的量词的各可能 值都要经过逐一测试，这将使最终的运算量达到一个很大的程度。这样，你将在电脑前等待相当长的时间才会看到结果。而如果用一次性子模式来改写刚才的模式， 改成这样/ ((?&gt;D+)&#124;&lt;d+&gt;)*[!?]/，你就可以很快得到运算的结果。<br />正则表达式快速入门（三）<br /><br />在上文里，我们介绍了正则表达式的子模式，逆向引用和量词，在这篇文章里，我们将重点介绍正则表达式中的断言(Assertions)。<br /><br />　　断言(Assertions)<br /><br />　　断言(Assertions)是在目标字符串的当前匹配位置进行的一种测试但这种测试并不占用目标字符串，也即不会移动模式在目标字符串中的当前匹配位置。<br /><br />　　读起来似乎有点拗口，我们还是举几个简单的例子。<br /><br />　　两个最常见的断言是元字符&ldquo;^&rdquo;和&ldquo;$&rdquo;，它们检查匹配模式是否出现在行首或行尾。<br /><br />　　我们来看这个模式/^ddd$/，试着用它来匹配目标字符串&ldquo;123&rdquo;。&ldquo;ddd&rdquo;表示三个数字字符，匹配了目标字符串的三个字符，而模式中的^和$分别表示这三个字符同时出现在行首和行尾，而它们本身并不与目标字符串中的任何字符相对应。<br /><br />　　其它还有一些简单的断言b, B, A, Z, z，它们都以反斜线开头，前面我们已经介绍过反斜线的这个用法。这几个断言的含义如下表。<br /><br />断言 含义 <br />b 字分界线 <br />B 非字分界线 <br />A 目标的开头（独立于多行模式） <br />Z 目标的结尾或位于结尾的换行符前（独立于多行模式） <br />z 目标的结尾（独立于多行模式） <br />G 目标中的第一个匹配位置 <br /><br /><br />　　注意这些断言不能出现在字符类中，如果出现了也是其它的含义，例如b在字符类中表示反斜线字符0x08。<br /><br />　　前面介绍的这些断言的测试都是一些基于当前位置的测试，断言还支持更多复杂的测试条件。更复杂的断言以子模式方式来表示，它包括前向断言(Lookahead assertions)和后向断言(Lookbehind assertions)。<br /><br />　　前向断言(Lookahead assertions)<br /><br />　　前向断言从目标字符串的当前位置向前测试断言条件是否成立。前向断言又可分为前向肯定断言和前向否定断言，分别用(?=和{?!表示。例如模式/ w+(?=;)/用来表示一串文本字符后面会有一个分号，但是这个分号并不包括在匹配结果中。一件有趣的事看起来差不多的模式/ (?=;)w+/并不是表示一串前面不是分号的alpha字符串，事实上，不论这串alpha字符的前面是否是一个分号它总是匹配的，要完成这个功能需要 我们下面提到的后向断言(Lookbehind assertions)。<br /><br />　　后向断言(Lookbehind assertions)<br /><br />　　后向断言分别用(?&lt;=和(?&lt;!表示肯定的后向断言与否定后向断言。例如，/ (?&lt;!foo)bar/将寻找一个前面不是foo的bar字符串。一般而言，后向断言使用的子模式需要有确定的长度值，否则会产生一个编译错误。 <br /><br />　　使用后向断言与一次性子模式搭配使用可以有效的文本的结束部分进行匹配，这里来看一下例子。<br /><br />　　考虑一下如果用/abcd$/这样一个简单的模式来匹配一长段以abcd结尾的文本，因为模式的匹配过程是从左向右进行的，正则表达式引擎将在文本中 寻找每一个a字符并尝试匹配剩余的模式，如果在这长段文本里仅好有不少的a字符，这样做明显是非常低效的，而如果把以上模式换成为样/^.*abcd$ /，这时前面的&ldquo;^.*&rdquo;部分将匹配整个文本，然后它发现下一个模式a无法匹配，这时会发生前面提到过的回溯过程，解析器会逐次缩短&ldquo;^.*&rdquo;匹配的字符 长度从右向左逐次查找剩余的子模式，也要产生多次的尝试过程。现在，我们用一次性子模式与后向断言重写所用的模式，改为/^(?&gt;.*)(? &lt;=abcd)/，这时，一次性子模式一次匹配了整段文本，然后用后向断言检查前面四个字符是否为abcd，只需要一次检测就可以立刻确定整个模式 是否匹配。在遇到需要匹配一个很长的文本时，这种方法可以非常显著的提高处理效率。<br /><br />　　一个模式中可以包含多个相继的断言，断言也可以嵌套。另外，断言使用的子模式也是非捕获的，不能被逆向引用。<br /><br />　　断言的一个重要应用领域就是做为条件子模式的条件。那什么是条件子模式呢？<br /><br />条件子模式(Conditional subpatterns)<br /><br />　　正则表达式允许在模式中根据不同的条件使用不同的匹配子模式。也就是条件子模式(Conditional subpatterns)。它的格式如下?(condition)yes-pattern)或者 (?(condition)yes-pattern&#124;no-pattern)。如果条件满足，采用yes-pattern，否则，采用no- pattern(如果在模式中提供了话)。<br /><br />　　条件子模式中的条件有两种，一种是断言结果，另一种是看是否捕获一个前面提供的子模式。<br /><br />　　如果在表示条件的圆括号里的内容是一个数字，它表示当此数字代表的子模式被成功匹配时条件为真。看看下面这个例子，/( ( )? [^()]+ (?(1) ) )/x，(注意&ldquo;x&rdquo;模式修正符表示忽略字符类外的空白字符和#符号之后的内容)。<br /><br />　　这个模式的第一部分&ldquo;( ( )?&rdquo;匹配了一个可选的左图括号&ldquo;(&rdquo;，第二部分&ldquo;[^()]+&rdquo;匹配了一个以上的非圆括号字符，最后一部分&ldquo;(?(1) ) )&rdquo;是个条件子模式，表示如果捕获到1也即那个可选的左圆括号，第三部分应该会出现一个右圆括号&ldquo;)&rdquo;。<br /><br />　　如果在表示条件的圆括号内是一个&ldquo;R&rdquo;字符，表示在这个模式或子模式被递归调用时条件为真，在递归调用的顶层，这个条件为假。关于正则表达式中的递归，我们会在后面的部分专题介绍。<br /><br />　　如果条件不是一个数字或R字符，则它必需是一个断言。断言可以是肯定或否定的前身或后向断言。让我们看下面这个例子。<br /><br />　　/(?(?=[^a-z]*[a-z])<br /><br />　　d{2}-[a-z]{3}-d{2} &#124; d{2}-d{2}-d{2} )/x<br /><br />　　为了让这个正则表达式更容易阅读，我们特意采用了x模式修正符，这样我们可以在用模式中加入空格对符式进行格式上的分隔并分行表示而不影响模式的解析。<br /><span style="font-size: xx-small; color: #c0c0c0">by clin003 from:<a href="http://clin003.com/" target="_blank">http://clin003.com/</a>或<a href="http://blog.csdn.net/cin003/" target="_blank">http://blog.csdn.net/cin003/</a></span><br />　　第一行的条件子模式使用了一个肯定的前向断言，表示一串可选的非小写字母后面跟随着一个小写字母。换句话说，它查看目标字符串是否至少包含一个小写字 母，如果是，它用&ldquo;&#124;&rdquo;前的模式对目标进行匹配，看目标是否为看目标是否为两个数字-三个小写字母-两个数字这种格式，否则，用&ldquo;&#124;&rdquo;来匹配目标，看目标 字符串是否为由&ldquo;-&rdquo;分隔的三段二位十进制数字。<br /><br />　　正则表达式中的注释<br /><br />　　为了让正则表达式更容易阅读，可以在其中加入注释语句。通常注释由左圆括号和井号&mdash;&mdash;&ldquo;(#&ldquo;开始，当遇到下一个右圆括号&rdquo;)&ldquo;结束。注释是禁止嵌套的。<br /><br />　　如果设定了&ldquo;x&rdquo;模式修正符，任何字符类之外(也即[]之外)的井号(#)和下一个新行标记之间的部分也被作为注释看待。<br />正则表达式快速入门（四）<br /><br />在上一篇文章里，我们介绍了正则表达式中断言相关的一些概念，在本文里，我们会介绍正则表达式中递归的运用与利用正则表达式修改目标字符串。<br /><br />　　正则表达式中的递归<br /><br />　　接触过程序的朋友可能都遇到过成对的各种括号吧，这些括号常常相互嵌套，而且嵌套的层次数目无法确定。试想一下如果想提取一段程序里用括号括起的一段代码，这里面很可能包含了层次数目不定的其它括号对，用正则表达式该如何完成?<br /><br />　　在Perl 5.6之前这的确有点困难，不过从Perl 5.6之后，引入了递归正则表达式，这个问题得到了解决。通常在正则表达式里用&ldquo;(?R)&rdquo;表示一个对自己的引用，下面让我们看看用什么正则表达式来解决刚才提出的问题。<br /><br />/( ( (?&gt;[^()]+) &#124; (?R) )* )/x <br /><br /><br />　　现在让我们来分析这个模式的含义，这里使用了&ldquo;x&rdquo;模式修正符，以便可以在模式中加入空格以方便阅读。<br /><br />　　模式的开头是匹配第一个左圆括号，然后我们需要捕获的子模式，注意，字模式后面跟了量词&ldquo;*&rdquo;，表示此模式可以重复0到多次。最后是一个结束圆括号。 现在我们分析子模式( (?&gt;[^()]+) &#124; (?R) )的内容。这是一个分支子模式，表示模式可以有两种情况，第一种是(?&gt;[^()]+)，这是一个一次性子模式，代表一个以上的非括号字符，另一种 情况是&#124; (?R)，也即对正则表达式自己的递归调用&mdash;&mdash;( ( (?&gt;[^()]+) &#124; (?R) )* )，又寻找一个左圆括号，开始查找一对嵌套的圆括号包含的内容。<br /><br />　　分析到这里，这个正则表达式的含义已经基本清楚，但你注意到没有，这里为什么要使用一次性子模式(?&gt;[^()]+)来查找非括号字符串?<br /><br />　　事实上，由于递归的层次是无限的，这种处理非常必要，特别是遇到不匹配的字符串时，它不会让你陷入长时间的等待。考虑一下下面这个目标字符串，<br /><br />　　(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()<br /><br />　　在得出不匹配的最终结果前，如果不使用一次性子模式，解析器将尝试每一种可能的方法来分割目标字符串，这将浪费大量的时间。<br /><br />用正则表达式修改目标<br /><br />　　并非所有的正则表达式工具都允许你修改目标字符串，它们中的一些仅仅使用正则表达式来查找匹配指定模式的字符串，在Linux中，最为广泛使用的支持 正则表达式的工具就是grep命令，这是一个专门用来查找的工具，再就是一些文本编辑器工具，它们有的允许使用正则表达式替换，有的则不允许，这需要查看 你使用的工具的在线手册。<br /><br />　　对于那些允许你使用正则表达式来修改目标字符串的工具中，它们之间的一些不同你必然放在心上:<br /><br />　　这些不同首先表现在替换的具体形式上，有的是以对话框的形式分别让你输入需要查找的模式和被替换的内容，有些则使用命令使界面通过定界符来分隔匹配的模式与需要替换的内容，对于一些编程语言工具，它们通常通过函数的不同参数来分别定义需要匹配的模式与替换的内容。<br /><br />　　另一个需要注意的不同是这些工具具体修改的对象。大多数基于Linux的命令行工具一般是通过标准输出或者管道来修改缓存的内容而非直接修改磁盘上存储的文件，而文本编辑器工具或编程语言通常会直接修改目标文件。<br /><br />　　我们下面用Linux下sed命令的格式来举几个正则表达式的例子:<br /><br />　　模式:s/cat/dog/g<br /><br />　　输入:wild dogs, bobcats, lions, and other wild cats<br /><br />　　输出:wild dogs, bobdogs, lions, and other wild dogs<br /><br />　　模式:s/[a-z]+i[a-z]*/nice/g<br /><br />　　输入:wild dogs, bobcats, lions, and other wild cats<br /><br />　　输出: nice dogs, bobcats, nice, and other nice cats<br /><br />　　当我们使用模式进行替换操作时，目标字符串中所有匹配模式的字符串都将被替换。<br /><br />　　下面再举一个使用逆向引用进行替换的例子:<br /><br />　　模式:s/([A-Z])([0-9]{2,4}) /2:1 /g<br /><br />　　输入: A37 B4 C107 D54112 E1103 XXX<br /><br />　　输出: 37:A B4 107:C D54112 1103:E XXX<br /><br />　　前面已经介绍过默认情况下的匹配一般是greedy的，这常会使实际匹配的部分大于你希望匹配的内容，特别是在进行替换操作时这将更加危险，因为如果 你在错误匹配的情况下执行了一次替换操作，实际上你是删除了目标中的有效内容，特别是当这种操作面向文件时造成的危害就更大了。因此，牢记一个不严格的字 符类加上一个不严格的量词足以造成不可挽回的后果，执行类似操作前一定要多测试一下不同的目标字符串，尽可能避免这种情况的发生。<br /><br />　　在本教程的下一篇文章里，我们会介绍一款可以方便进行正则表达式学习的工具和一些正则表达式编写的思路。<br />正则表达式快速入门（五）<br /><br />在上一篇文章里，我们介绍了正则表达式中的递归与替换，现在让我们接触一个学习正则表达式时方便测试使用的工具，并介绍一些正则表达式的编写思路。<br /><br />　　一个学习正则表达式的便捷工具<br /><br />　　学习正则表达式最好的方法当然是实践，不过支持正则表达式的工具虽多，但如果仅仅用来做练习却不是很方便。<br /><br />　　这里我向一家推荐一款专门的正则表达式编写测试工具，PHPEdit公司的Regular Expression Editor工具。这是一个免费软件，主要用来调试PHP使用的Perl兼容正则表达式函数。使用它可以方便的输入目标字符串和正则表达式，并实时看到匹 配的结果。可以到它的下载网页去下载这个工具。<br /><br />　　程序的界面非常简明，不过使用中发现，它的一些功能使用起来好像有问题，只有preg_match_all和preg_replace功能正常，另外在匹配模式输入框中，不要加模式定界符，程序好像把该输入框中的全部内容都作为模式来解析。<br /><br />　　好在做为一个正则表达式的练习工具，它的功能是足够了，下面是它的运行界面。<br /><br /><br />程序运行界面<br /><br />　　文中提到的各个例子都可以在里面进行测试，在最上面的框里输入模式，把目标字符串写进中间的输入框，点击&ldquo;run the regxwp&rdquo;按钮可以在下面得到匹配结果。<br /><br />正则表达式的编写思路<br /><br />　　一个避免过多匹配的小技巧<br /><br />　　前面我们已经多此谈到书写不合理的正则表达式引起过多匹配的问题，现在的问题是，如何可以尽量避免类似的情况发生。这里有个小小的技巧。<br /><br />　　如果你发现你定制模式匹配了过多的结果，一个好的方法是换个思路，与其考虑我的模式下一步需要匹配什么，不如考虑我的模式下一步需要避免匹配什么。我们可以用元字答&ldquo;^&rdquo;和字符类很容易的达成这种效果，这常常可以得到更精确的匹配。<br /><br />　　为了说明这种思路的好处我们先来举一个与正则表达式无关的例子，考虑这样一个问题，你把一个骰子一次抛出6的概率是六分之一，如果让你掷六次，掷出一个6的概率是多少呢?<br /><br />　　可能有人会这么算，一次的概率是1/6，六次是就是6个1/6，加起来等于1。这个结果明显是错的，虽然你掷了六次，但肯定不能保证必然会掷出一个6。从正向的思路解这道题看上去有点难。<br /><br />　　如果我们换个思路，解决的方法就明确多了。我们可以把这个题的问法改成这样，如果让你掷6次骰子，每一次都掷不出6的概率是多少?这个问题就好解多 了，根据概率的乘法原理，每一次掷出不是6的点数的概率是5/6，而6次中每一次都不是6的概率是5/6的6次方，大概等于33%的样子，然后用1减去这 个数字就可以得到我们需要的答案。<br /><br />　　你可以把模式中每部分的匹配看作掷一次骰子的过程，每一部分的匹配概率与总匹配概率的情况与我们上面这个例子非常相似。<br /><br />　　如何提高正则表达式的解析效率<br /><br />　　对同样匹配内容的正则表达式而言，一些模式往往比另外一些模式更有效率。举一个简单的例子，使用字符类&ldquo;[aeiou]&rdquo;会比使用分支选择型模式&ldquo;(a&#124;e&#124;i&#124;o&#124;u).&rdquo;更有效，一般而言，使用尽可能简单和基本的模式通过会得到更高的效率。<br /><br />　　应该尽可能的慎用相互嵌套的无限重复量词，当遇到不匹配的目标字符串时，对字符串的解析有可能花掉很可观的时间。比如下面这个模式片断&ldquo;(a+) *&rdquo;，当遇到不匹配的目标字符串&ldquo;aaaa&rdquo;时，解析器会对它尝试33种不同的匹配方法，这个数目会随不匹配字符串长度的增加而极快的增长。<br /><br />　　一些正则表达式工具对一些特定的模式匹配进行了优化以提高效率，了解你使用的正则表达式工作做过些什么优化并尽可能利用经过优化的模式可以大大提高你 的正则表达式执行效率。例如，PHP对形如/a+)*b /这样的模式的解析进行了优化，当模式结尾是一个确定的字符时，解析器会先查找目标的结尾是否符合模式，如果否则立刻返回失败的匹配结果并停止解析。如果 将上面的样式改为&ldquo;(a+)*d&rdquo;时，因为结尾不再是一个确定的字符，此模式会按正常的过程解析。如果你想看一下两者效果的差异，你在我们前面提到的工具 中，把目标字符串设置成25个小写的a字符，然后分别测试两个模式，前者立刻就结束了，而后者需要等待约一秒(笔者使用的是XP1700+处理器)。<br /><br />　　除了尽可能利用经过优化的模式，对一些模式进行重新构造也可以大大提高效率。我们在介绍后向断言时介绍过的那个利用后向断言结合一次性子模式匹配结尾的字符的方法就是一个很好的例子。<br /><br />　　这里我们准备结束这个教程，由于篇幅和本人水平的限制文中可能会有很多疏漏，还要请求大家谅解。对正则表达式介绍最全面的可能还是Perl相关的一些 文档和著作，如果想对正则表达式进行更深入的了解可以参看Jeffrey Friedl 写的&ldquo;Mastering Regular Expressions&rdquo;一书，里面有很多例子。不过我觉得在了解正则表达式基本概念后，还是仔细读一下自己经常使用的相关工具里的正则表达式相关部分更 实用一些，最后，还是那句话，实践出真知，希望大家在不断实践中更好的掌握正则表达式的使用。<br />正则表达式中的特殊字符<br /><br />转自：<a href="http://www.phpe.net/articles/151.shtml" target="_blank">http://www.phpe.net/articles/151.shtml</a> <br /><br />字符 描述 <br /><br />将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。例如，'n' 匹配字符 &quot;n&quot;。'n' 匹配一个换行符。序列 '' 匹配 &quot;&quot; 而 &quot;(&quot; 则匹配 &quot;(&quot;。<br />^<br />匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性，^ 也匹配 'n' 或 'r' 之后的位置。<br />$<br />匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性，$ 也匹配 'n' 或 'r' 之前的位置。<br />*<br />匹配前面的子表达式零次或多次。例如，zo* 能匹配 &quot;z&quot; 以及 &quot;zoo&quot;。 * 等价于{0,}。<br />+ 匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 &quot;zo&quot; 以及 &quot;zoo&quot;，但不能匹配 &quot;z&quot;。+ 等价于 {1,}。<br />?<br />匹配前面的子表达式零次或一次。例如，&quot;do(es)?&quot; 可以匹配 &quot;do&quot; 或 &quot;does&quot; 中的&quot;do&quot; 。? 等价于 {0,1}。<br />{n}<br />n 是一个非负整数。匹配确定的 n 次。例如，'o{2}' 不能匹配 &quot;Bob&quot; 中的 'o'，但是能匹配 &quot;food&quot; 中的两个 o。<br />{n,}<br />n 是一个非负整数。至少匹配n 次。例如，'o{2,}' 不能匹配 &quot;Bob&quot; 中的 'o'，但能匹配 &quot;foooood&quot; 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。<br />{n,m}<br />m 和 n 均为非负整数，其中n &lt;= m。最少匹配 n 次且最多匹配 m 次。刘， &quot;o{1,3}&quot; 将匹配 &quot;fooooood&quot; 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。<br />?<br />当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时，匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串，而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如，对于字符串 &quot;oooo&quot;，'o+?' 将匹配单个 &quot;o&quot;，而 'o+' 将匹配所有 'o'。<br />. <br />匹配除 &quot;n&quot; 之外的任何单个字符。要匹配包括 'n' 在内的任何字符，请使用象 '[.n]' 的模式。<br />(pattern)<br />匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到，在VBScript 中使用 SubMatches 集合，在JScript 中则使用 {CONTENT}&hellip; 属性。要匹配圆括号字符，请使用 '(' 或 ')'。<br />(?:pattern)<br />匹配 pattern 但不获取匹配结果，也就是说这是一个非获取匹配，不进行存储供以后使用。这在使用 &quot;或&quot; 字符 (&#124;) 来组合一个模式的各个部分是很有用。例如， 'industr(?:y&#124;ies) 就是一个比 'industry&#124;industries' 更简略的表达式。<br />(?=pattern)<br />正向预查，在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如， 'Windows (?=95&#124;98&#124;NT&#124;2000)' 能匹配 &quot;Windows 2000&quot; 中的 &quot;Windows&quot; ，但不能匹配 &quot;Windows 3.1&quot; 中的 &quot;Windows&quot;。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始。<br />(?!pattern)<br />负向预查，在任何不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如'Windows (?!95&#124;98&#124;NT&#124;2000)' 能匹配 &quot;Windows 3.1&quot; 中的 &quot;Windows&quot;，但不能匹配 &quot;Windows 2000&quot; 中的 &quot;Windows&quot;。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始<br />x&#124;y <br />匹配 x 或 y。例如，'z&#124;food' 能匹配 &quot;z&quot; 或 &quot;food&quot;。'(z&#124;f)ood' 则匹配 &quot;zood&quot; 或 &quot;food&quot;。<br />[xyz]<br />字符集合。匹配所包含的任意一个字符。例如， '[abc]' 可以匹配 &quot;plain&quot; 中的 'a'。<br />[^xyz]<br />负值字符集合。匹配未包含的任意字符。例如， '[^abc]' 可以匹配 &quot;plain&quot; 中的'p'。<br />[a-z]<br />字符范围。匹配指定范围内的任意字符。例如，'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。<br />[^a-z]<br />负值字符范围。匹配任何不在指定范围内的任意字符。例如，'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。<br />b<br />匹配一个单词边界，也就是指单词和空格间的位置。例如， 'erb' 可以匹配&quot;never&quot; 中的 'er'，但不能匹配 &quot;verb&quot; 中的 'er'。<br />B<br />匹配非单词边界。'erB' 能匹配 &quot;verb&quot; 中的 'er'，但不能匹配 &quot;never&quot; 中的 'er'。<br />cx<br />匹配由x指明的控制字符。例如， cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一个原义的 'c' 字符。<br />d<br />匹配一个数字字符。等价于 [0-9]。<br />D<br />匹配一个非数字字符。等价于 [^0-9]。<br />f<br />匹配一个换页符。等价于 x0c 和 cL。<br />n<br />匹配一个换行符。等价于 x0a 和 cJ。<br />r<br />匹配一个回车符。等价于 x0d 和 cM。<br />s<br />匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [ fnrtv]。<br />S<br />匹配任何非空白字符。等价于 [^ fnrtv]。<br />t<br />匹配一个制表符。等价于 x09 和 cI。<br />v<br />匹配一个垂直制表符。等价于 x0b 和 cK。<br />w<br />匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。<br />W<br />匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。<br />xn<br />匹配 n，其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如， 'x41' 匹配 &quot;A&quot;。'x041' 则等价于 'x04' &amp; &quot;1&quot;。正则表达式中可以使用 ASCII 编码。.<br />num<br />匹配 num，其中 num 是一个正整数。对所获取的匹配的引用。例如，'(.)' 匹配两个连续的相同字符。<br />n<br />标识一个八进制转义值或一个后向引用。如果 n 之前至少 n 个获取的子表达式，则 n 为后向引用。否则，如果 n 为八进制数字 (0-7)，则 n 为一个八进制转义值。<br />nm<br />标识一个八进制转义值或一个后向引用。如果 nm 之前至少有is preceded by at least nm 个获取得子表达式，则 nm 为后向引用。如果 nm 之前至少有 n 个获取，则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足，若&nbsp;&nbsp;n 和 m 均为八进制数字 (0-7)，则 nm 将匹配八进制转义值 nm。<br />nml<br />如果 n 为八进制数字 (0-3)，且 m 和 l 均为八进制数字 (0-7)，则匹配八进制转义值 nml。<br />un<br />匹配 n，其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如，u00A9 匹配版权符号 (?)。<br/>Tags - <a href="tag.php?tag=php%E6%AD%A3%E5%88%99" rel="tag">php正则</a> , <a href="tag.php?tag=php" rel="tag">php</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?143</link>
<title><![CDATA[一行代码杜绝iframe挂马]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[学习与实践]]></category>
<pubDate>Mon, 14 Jan 2008 05:51:25 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?143</guid> 
<description>
<![CDATA[ 
	<span style="font-size: small"><span style="color: teal"> 相信大多数站长都曾经遭遇过iframe木马的侵害，有朋友的网站被注入了N回iframe，心情可想而知。而且现在ARP攻击，注入iframe也是轻而易举的事，仅局域网里都时刻面临威胁<br /> 今天把原理细细地讲一下吧：</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">IE Only&mdash;&mdash;一般只有IE害怕iframe这样的挂马,所以就拿IE开刀。</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">在阅读本文之前，我们先了解一下expression；</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">IE5及其以后版本支持在CSS中使用expression，用来把CSS属性和 JavaScript脚本关联起来，这里的CSS属性可以是元素固有的属性，也可以是 自定义属性。就是说CSS属性后面可以是一段JavaScript表达式，CSS属性的值等于Javascript表达式执行的结果。在表达式中可以直接 引用元素自身的属性和方法，也可以使用其他浏览器对象。这个表达式就好像是在这个元素的一个成员函数中一样。</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">很多朋友都知道CSS可以直接描述一个可视标记的外观。例如：p{color:red} 则网页里 所有p标记里的文字颜色都会变成红色;iframe不也是一个标记吗？开始跟灵儿写代码吧，呵呵：<br /> iframe{...这里写描述外观的CSS代码;};</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">仔细想想要防止iframe里的东东被下载的最好办法是什么？核心来了，那就是切断iframe里的请求，切断请求就是要迅速销毁iframe对象。如何实现呢，上面不是介绍了expression吗？expression是可以执行JS脚本的哈。语法格式如下二种：</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">标记固有的CSS属性名:expression(JS表达式);<br /> 或 自定义属性名:expression(JS表达式);</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">在这里我们选择第二种，代码应该大致是这样<br /> iframe{v:expression(JS表达式);}</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">接下来的问题是如何销毁网页里所有的iframe对象；使用JS实现的原理是这样 的:使iframe里的请求地址变成空白页(about:blank)，再将iframe对象从DOM（文档对象模型）中移除就可以切断所有iframe 里的请求了。移除DOM节点的方法比较多，我这里就用 outerHTML这个属性吧。CSS代码如下：<br /> iframe{v:expression(this.src='about:blank',this.outerHTML='');}</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">说明：前面的v字是灵儿自己定义的一个CSS属性，这里的this代表所有将要描 述外观的iframe对象，中间的逗号代表二句代码一起执行，没有执行优先顺序，这可是强有力的保证噢。about:blank代表空白页，大家都知道 的。outerHTML属性是DOM对象包含自身的HTML代码，而innerHTML则是DOM对象（不含本身）里面所包含的HTML代码。</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">爽快，代码写好了，就让我信来测试一下有没有效果。</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">首先，新建一个网页，插入以上的CSS代码(或在您现有的CSS代码里加入上面那句)：<br /> &lt;style type=&quot;text/css&quot;&gt;<br /> iframe{v:expression(this.src='about:blank',this.outerHTML='');}<br /> &lt;/style&gt;</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">然后在这个页面插入几个IFRAME代码，假设它们是被挂的木马网页。代码如下：<br /> <span><span style="color: red">&lt;iframe xsrc=&quot;&quot;&gt;&lt;/iframe&gt; </span></span></span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span><span style="color: red">&lt;iframe xsrc=&quot;</span></span></span><span style="font-size: small"><a href="http://www.haoexe.com/" target="_blank"><span><span style="color: red">http://blog.sust.net.ru/&quot;&gt;&lt;/iframe</span></span></a></span><span style="font-size: small"><span style="color: red">&gt;草讯<br /> &lt;iframe xsrc=&quot; </span></span><span style="font-size: small"><a href="http://www.haoexe.com/" target="_blank"><span><span style="color: red">http://</span></span></a></span><a href="http://www.haoexe.com/" target="_blank"><span><span></span></span></a><span><span><span style="font-size: small"><a href="http://www.haoexe.com/" target="_blank"><span><span style="color: red">blog.sust.net.ru</span></span></a></span></span></span><span style="font-size: small"><a href="http://www.haoexe.com/" target="_blank"><span><span style="color: red">/&quot;&gt;&lt;/iframe</span></span></a></span><span style="font-size: small"><span style="color: red">&gt; 涩果</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">保存为noiframe.htm，打开浏览器测试一下（本地测试需要启用顶部禁用 的脚本的提示条哦）。我这里使用抓包工具来测试，不过也没有必要使用抓包工具，一个最简单有效的方法是打开IE的缓存文件夹，先清空它，再刷新这个页面， 看看缓存文件夹里有没有这三个网站里的文件。如果没有，说明没有任何请求结果被返回&mdash;&mdash;测试结果是令人满意的，我的脸上有些微笑 ^^*，这时同事递给我一块饼，蛮好吃的。</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">提示：Windows XP SP2的缓存文件夹位置　C:&#92;Documents and Settings&#92;Administrator&#92;Local Settings&#92;Temporary Internet Files</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">细心的朋友发现问题来了，如果我自己的网页里要使用iframe这个东东怎么办？</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">答：如果要使自己的iframe显示在网页里，而别人挂的IFRAME马都不起作用，在CSS里加一个<br /> #haoexe{v:expression() !important}</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">对应的IFRAME代码为：<br /> &lt;iframe id=&quot;haoexe&quot; name=&quot;haoexe&quot; xsrc=&quot;</span></span><span style="font-size: small"><a href="http://www.haoexe.com/" target="_blank"><span><span style="color: teal">http://www.haoexe.com/&quot;&gt;&lt;/iframe</span></span></a></span><span style="font-size: small"><span style="color: teal">&gt;<br /> 就OK了。</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">提示：IE7中优先执行标注有&quot;!important&quot;描述的样式，IE6不认识!important，采用就近原则，所以IE6的这个代码放在CSS的最后就可以了。</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">这里的f126，有很多朋友有疑问，他们问我为什么取&quot;f126&quot;，我这样回答&mdash;&mdash;这个f126是随意取的，只要下面的iframe里的ID属性和CSS里的一致就行了。同事又要递一块饼我吃，我说饱了哈..嘻嘻..</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">当然挂马者可以构造这样的代码<br /> &lt;iframe style=&quot;v:expression() !important&quot; xsrc=&quot;URL&quot;&gt;&lt;/iframe&gt;<br /> 使我的防御方式失效，不过它得特意去看我的CSS代码里iframe里的前缀v,如果我的v是变化的呢，哈哈，是不是也不管用呢！</span></span><span style="font-size: small"><br /></span> <span style="font-size: small"><span style="color: teal">小结：以上的方法只是停止了iframe的请求并销毁了它本身，但以后的挂马方式改变了，例如改成<br /> &lt;script&gt;&lt;/script&gt;<br /> 方式挂，就不能用这种方法来解决了；此这个方法不是最终的解决案，最终的解决方案是找出真正被挂IFRAME的原因，堵住源头。这可不是我的事哈!</span></span>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?142</link>
<title><![CDATA[推荐:MySQL密码恢复笔记]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[学习与实践]]></category>
<pubDate>Tue, 11 Dec 2007 07:18:49 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?142</guid> 
<description>
<![CDATA[ 
	<p>因为My<span class="t_tag">SQL</span><span class="t_tag">密码</span>存储于<span class="t_tag"><span class="t_tag"><a href="http://www.3800hk.com/" class="channel_keylink">数据</a></span>库</span><span class="t_tag">mysql</span>中的user表中<br />所以只需要将我windows 2003下的MySQL中的user表拷贝过来覆盖掉就行了<br />在c:&#92;mysql&#92;data&#92;mysql&#92;(linux 则一般在/var/lib/mysql/mysql/)目录下有三个user表相关文件user.frm、user.MYD、user.MYI<br />user.frm //user表样式文件<br />user.MYD //user表<a href="http://www.3800hk.com/" class="channel_keylink">数据</a>文件<br />user.MYI //user表索引文件<br />为保险起见，三个都拷贝过来，不过其实如果之前在要恢复的那个MySQL上没有更改过表结构的话，只要拷贝user.MYD就行了<br />然后#. /etc/rc.d/init.d/mysql stop<br />#. /etc/rc.d/init.d/mysql start<br />#mysql -u root -p XXXXXX<br />好了，可以用windows 2003下mysql密码登陆了<br />mysql&gt;use mysql<br />mysql&gt;update user set Password=PASSWORD('xxxxxx') where User='root';<br />这时候会出错，提示user表只有读权限<br /><br />我<span class="t_tag">分析</span>了一下原因，只这样的，因为user.*文件的权限分配是windows 2003下的，在windows 2003下我ls -l一看权限是666<br />在linux下我一看，拷过来后权限变成了600(其实正常情况下600就行了，只不过这里的文件属主不是mysql，拷过来后的属主变为了root,所以会出现权限不够，这时候如果你改成权限666则可以了，当然这样不好，没有解决问题的实质)，在/var/lib/mysql/mysql/下ls -l看了一下再<br />#chown -R mysql:mysql user.*<br />#chmod 600 user.*<br />//OK,DONE<br />重起一下MYSQL<br />重新连接<br />mysql&gt;use mysql<br />mysql&gt;update user set Password=PASSWORD('xxxxxx') where User='root';<br />mysql&gt;FLUSH PRIVILEGES;<br />有一点值得注意:如果你windows 下mysql如果是默认<span class="t_tag">配置</span>的话，注意要还要执行<br />mysql&gt;delete from user where User='';<br />mysql&gt;delete from user where Host='%';<br />mysql&gt;FLUSH PRIVILEGES;<br />好了，到这里恢复密码过程就完成了<br />这个方法么就是有点局限性，你必须也具备另外的user表文件<br /><br />其他还有几种方法<br /><br />其它方法一(这个是网上流传较广的方法,mysql中文参考<span class="t_tag">手册</span>上的)<br />1. 向mysqld <span class="t_tag">server</span> 发送kill命令关掉mysqld <span class="t_tag">server</span>(不是 kill -9),存放进程ID的文件通常在MYSQL的<a href="http://www.3800hk.com/" class="channel_keylink">数据</a>库所在的目录中。<br />killall -TERM mysqld<br />你必须是<span class="t_tag">UNIX</span>的root<span class="t_tag">用户</span>或者是你所运行的SERVER上的同等<span class="t_tag">用户</span>，才能执行这个操作。<br />2. 使用`--skip-grant-tables' 参数来启动 mysqld。 (LINUX下/usr/bin/safe_mysqld --skip-grant-tables , windows下c:&#92;mysql&#92;bin&#92;mysqld --skip-grant-tables)<br /><br />3. 然后无密码登录到mysqld server ，<br />&gt;use mysql<br />&gt;update user set password=password(&quot;new_pass&quot;) where user=&quot;root&quot;;<br />&gt;flush privileges;<br />。你也可以这样做：`mysqladmin -h hostname -u user password 'new password''。<br /><br />4. 载入权限表： `mysqladmin -h hostname flush-privileges' ，或者使用 SQL 命令`FLUSH PRIVILEGES'。<br />5.killall -TERM mysqld<br />6.用新密码登陆<br /><br />其它方法二<br /><br />直接用十六进制编辑器编辑user.MYD文件<br /><br />不过这个里面我要说明一点，我这里编辑的时候发现个问题，<span class="t_tag">加密</span>的密码串有些是连续存储的，有些的最后两位被切开了，后两位存储在后面其他地方.这一点我还没想明白.还有注意一点就是编辑的是<span class="t_tag">加密</span>过的密码串，也就是说你还是需要另外有user表文件。这种方法和我最上面<span class="t_tag">介绍</span>的方法的区别在于，这种方法直接编辑linux下的user表文件，就不需要重新改文件属主和权限了</p><br/>Tags - <a href="tag.php?tag=%E5%AF%86%E7%A0%81" rel="tag">密码</a> , <a href="tag.php?tag=mysql" rel="tag">mysql</a>
]]>
</description>
</item><item>
<link>http://blog.sust.net.ru/read.php?141</link>
<title><![CDATA[推荐:简单认识Anti-RootKit]]></title> 
<author>pling &lt;admin@oneter.com&gt;</author>
<category><![CDATA[技术和经验]]></category>
<pubDate>Mon, 05 Nov 2007 19:39:25 +0000</pubDate> 
<guid>http://blog.sust.net.ru/read.php?141</guid> 
<description>
<![CDATA[ 
	现在RK（rootkit）和ARK(anti-rootkit)的斗争已经进行了很久，在印象中最早出来的ARK工具是冰刃(IceSword)，从冰刃开始出来到现在RK和ARK的斗争一直在继续，目前冰刃还是在流行当中，自己感觉也正是冰刃的出来才带动了当前流行的RK和ARK的斗争&nbsp;呵呵，现在很多病毒木马已经广泛的带有驱动,使用一些RK的<a href="http://www.3800hk.com/" class="channel_keylink">技术</a>和方法使自己更底层些更强大些，当前流行的ARK工具主要包括：隐藏进程检测，内核驱动检测，SSDT检测，代码HOOK检测，注册表隐藏的检测，隐藏文件的检测等一些功能的，下面谈谈自己对一些功能的简单愚见&nbsp;嘻嘻。 <br /><br />关于进程检测：其实最早在R3下隐藏进程的方法已经很早开始流行起来被用到各种软件上来，在R0下如断ActiveProcessLinks链，擦掉句柄表等等，一步步的发展渐渐的更强大起来一些技巧和方法开始出来和流行起来，如FUTO，phide_ex等。。。。。。 <br /><br />检测隐藏进程的方法可以把一些现在流行的方法组合起来用，首先可以通过进程的EPROCESS结构中的进程活动链表ActiveProcessLinks来进行扫描一边，可以通过进程句柄表的枚举通过EPROCESS的HANDLE_TABLE，HANDLE_TABLE结构中的HandleTableLis链表来扫描一边来获得一些EPROCESS，可以通过定位PsLookupProcessByProcessId代码中的PspCidTable链表扫描一边获得一些EPROCESS，PspCidTable在各系统中枚举是不太一样的，也可以通过先找出KiWaitInListHead，KiWaitOutListHead和KiDispatcherReadyListHead这些链表然后对这些链表扫描获得一些EPROCESS，以上具体的实现代码可以GOOGLE之网上实现的代码已经很多了，再者也可以找到内核中的线程切换SwapContext函数进行HOOK下的，在自己实现的SwapContext函数根据线程的偏移量找出进程的EPROCESS结构，把上面获得的所有EPROCESS汇集起来还需要判断下当前进程是否是真正的活着的：）可以通过EPROCESS里的标志位Flags（如XP&nbsp;下0x248）一些标志判断下的，还要注意下对上面这些链表汇集起来是会有重复的进程的，在你自己的汇集函数中根据EPROCESS判断下的&nbsp;废话了，感觉实现了上面的一些方法对付一般的隐藏进程已经足够了的，但厉害的RK还是有的，现在存在可以逃过这些方法的RK的，在进程EPROCESS的结构里偏移0x1f8（XP&nbsp;SP2下）有个struct&nbsp;&nbsp;MMSUPPORT&nbsp;Vm结构： <br /><br />struct&nbsp;_MMSUPPORT <br />{ <br />/*&nbsp;off&nbsp;0x00000000&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;union&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;LastTrimTime; <br />/*&nbsp;off&nbsp;0x00000008&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;&nbsp;MMSUPPORT_FLAGS&nbsp;&nbsp;&nbsp;&nbsp;Flags; <br />/*&nbsp;off&nbsp;0x0000000C&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;PageFaultCount; <br />/*&nbsp;off&nbsp;0x00000010&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;PeakWorkingSetSize; <br />/*&nbsp;off&nbsp;0x00000014&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;WorkingSetSize; <br />/*&nbsp;off&nbsp;0x00000018&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;MinimumWorkingSetSize; <br />/*&nbsp;off&nbsp;0x0000001C&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;MaximumWorkingSetSize; <br />/*&nbsp;off&nbsp;0x00000020&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;_MMWSL*&nbsp;&nbsp;&nbsp;&nbsp;VmWorkingSetList; <br />/*&nbsp;off&nbsp;0x00000024&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;LIST_ENTRY&nbsp;&nbsp;&nbsp;&nbsp;WorkingSetExpansionLinks; <br />/*&nbsp;off&nbsp;0x0000002C&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;Claim; <br />/*&nbsp;off&nbsp;0x00000030&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;NextEstimationSlot; <br />/*&nbsp;off&nbsp;0x00000034&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;NextAgingSlot; <br />/*&nbsp;off&nbsp;0x00000038&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;EstimatedAvailable; <br />/*&nbsp;off&nbsp;0x0000003C&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;GrowthSinceLastEstimate; <br />}; <br /><br />在这个结构里+0x24有个&nbsp;&nbsp;&nbsp;&nbsp;WorkingSetExpansionLinks他也是个LIST_ENTRY链表的，遍例下他可以获得进程的EPROCESS的，如 <br />PEPROCESS&nbsp;eprocess,&nbsp;eprocess2 <br />eprocess&nbsp;=PsGetCurrentProcess(); <br />lp=(PLIST_ENTRY)(*(PVOID&nbsp;)((PUCHAR)eprocess+0x1f8+0x24+4)); <br />cur&nbsp;=lp-&gt;Flink; <br />for(;cur!=lp;cur=cur-&gt;Flink) <br />{ <br />eprocess2=(PEPROCESS)((ULONG)cur-0x1f8-0x24); <br />PVOID&nbsp;session=&nbsp;(PVOID)(*(PULONG)((PCHAR)&nbsp;eprocess2+&nbsp;0x170)); <br />if(MmIsAddressValid(session)){ <br />AddProcess(eprocess2); <br />} <br />} <br /><br />再者在进程EPROCESS的结构里偏移0x0b4（XP&nbsp;SP2下）存在个struct&nbsp;_LIST_ENTRY&nbsp;&nbsp;&nbsp;&nbsp;SessionProcessLinks结构，他也是个链表的&nbsp;：）通过遍例他也可以的获得一些EPROCESS。还有个地方可以的&nbsp;呵呵&nbsp;在每个线程对象里（ETHREAD）偏移0x34里有个struct&nbsp;_KAPC_STATE&nbsp;ApcState&nbsp;结构的在_KAPC_STATE结构里偏移0x10，再者也可以通过遍例内存来查找隐藏进程，从内存MmSystemRangeStart开始到System进程的EPROCESS地址就可以了主要是判断这个地址是否是个有效的进程，方法挺多的如判断下是否是进程对象这个地址如果是EPROCESS看看PID，ThreadListHead，ReadyListHead是否正确有效的等等，很多方法的应该组合起来判断下保证肯定是进程就可以了，还可以通过HOOK一些函数的如KeUpdateRunTime，KeDispatchInterrupt等来检测隐藏进程，还可以设置下PsSetCreateProcessNotifyRoutine在每次进程创建的时候对线程插入个APC的来进行统计检测的，其实我觉得对于检测隐藏进程的方法技巧还有很多，伟大的WINDOWS还需要我们挖掘呀。进程的结束可以通过调用ZwTerminateProcess或者调用未公开的PspTerminateProcess函数的，关于这个函数在网上已经很广泛了，可以通过遍例进程的每个线程调用PspTerminateThreadByPointer的结束每个线程的，这些未公开的函数都需要事先的查找和定位的，还可以使用RKU（RkUnhooker）的内存清零大法的切换到该进程然后对该进程内存清零RtlZeroMemory，再者也可以对该进程的每个线程插入APC来结束进程的，最后如果你有时间你也可以通过观看2K的代码自己来实现进程的结束。 <br />内核驱动检测首先你可以通过ZwQuerySystemInformation的SystemModuleInformation功能号来枚举内核驱动的，然后可以通过打开目录对象,进行枚举代码就略了GOOGLE之吧，也可以通过枚举IoDriverObjectType和IoDeviceObjectType对象类型进行查找枚举顺便把他们的DeviceObject和AttachedDevice等也枚举下吧，接着可以通过查找PsLoadedModuleList对该链进行下枚举的，可以对这个目录对象再搜索一边的&rdquo;&#92;&#92;Driver&rdquo;。通过对上面这些方法的枚举可以查找到很多驱动对象了，相信现在你的驱动对象链表已经够多了&nbsp;嘿嘿，够累吧，接下来，你可以对上面你已经查找到的驱动对象的0x38偏移MajorFunction查找一边看看他的地址是否在已知的驱动地址范围内，如不在你知道该怎么办的，再对MajorFunction里的每个例程地址找一边的从0到28也看看他们的地址是否在已知的驱动地址范围内，最后再说一种的方法的，也可以像进程那样内存枚举的，像进程那样从MmSystemRangeStart开始枚举吧，判断下是否是PE文件有没有那几个关键PE特征的，如MZ，PE等，看看是否存在PE文件头是否有效，看看这个地址是否已经是你检测出来的驱动地址的，避免重复的，看看你所检测出来的所有驱动对象的MajorFunction[X]和DriverStartIo是否有在这个地址，如果有并且这个地址你先前没有检测出来没有重复的他很有可能是个未知的驱动的，其实和进程内存查找一样的，关键是判断的，需要判断对的，肯定他是某个对象的然后你就可以把他加如到你自己的某个链表里。最后也可以通过对一些关键函数的HOOK&nbsp;如ExAllocatePool，ExAllocatePoolWithTag等在自己实现这些函数里记录下esp+0x24地址的，对这些地址进行判断的来看看这些地址是否包含在某些内核模块当中当然还需要判断下他是否就是个PE驱动文件，这种方法就是RKU用到的方法的。驱动就说这些吧。 <br /><br />前面说得太多了，后面说少点吧&nbsp;嘿嘿。 <br /><br />关于SSDT&nbsp;HOOK的检测，通过定位ntoskrnl.exe磁盘文件里KeServiceDescriptorTable与内存中的KeServiceDescriptorTable对各个<a href="http://www.3800hk.com/" class="channel_keylink">服务</a>函数进行比较就可以的。代码网上很多的。 <br /><br />关于代码HOOK检测，我也不想说什么的，可以对内存中ntoskrnl.exe&nbsp;的导入函数和导出函数与磁盘文件中的地址进行比较，也可以通过对ntoskrnl.exe&nbsp;PE文件里的某些节（section）进行扫描的，再加上对一些关键文件的导入函数和导出函数进行扫描，加上对某些关键驱动（如文件系统驱动）的MajorFunction里的每个例程进行扫描，再者对IDT，GDT扫描下的。 <br /><br />关于注册表隐藏的检测，首先可以用到把一些注册表相关的函数INLINE&nbsp;HOOK的SSDT&nbsp;HOOK的都恢复下再使用的其实所谓的不相关的也需要UNHOOK下的，如badrkdemo&nbsp;他就HOOK了ObOpenObjectByName函数组织对注册表的访问的&nbsp;具体的看情况来吧&nbsp;哈哈，也可以通过对一些未公开的函数进行使用的CM系列函数的，再者可以通过分析HIVE文件的来显示注册表各个项的，通过分析HIVE文件其实也不是很难的，了解了HIVE文件结构和HIVE文件的组织的，就可以读他了，这些资料网上可以找到的，通过读HIVE文件来给用户显示当前注册表各个项的可以的但我并不推荐自己改写系统的HIVE文件的，如提供DELETE&nbsp;MODIFE等功能的我觉得如改的不好，或结构没有完全清楚的，写到HIVE文件里是错误的，那么当再次启动时系统读HIVE文件时就不好过了，自己一点愚见，如果你够强大当然是没有问题的。 <br /><br />关于隐藏文件的检测，现在流行的隐藏文件的RK很多的，如Unreal.A，AK922等，自己可以通过在驱动中自己构建IRP包自己发送给文件驱动的方法的，还有就是先恢复些关键函数的，像注册表那样的，恢复INLINE&nbsp;HOOK&nbsp;SSDT&nbsp;HOOK，文件驱动关键例程HOOK的，现在流行HOOK内核的完成例程的，HOOK是防不胜防的，还要注意下附加在文件系统上的一些过滤驱动的，还有就是通过使用DeviceIoControl发送一些特殊的IoControlCode控制代码给文件系统的，这需要对文件系统的熟悉的，还有就是自己分析磁盘文件的对FAT32，NTFS等格式文件系统自己分析来查找文件的，关于自己分析磁盘文件的，网上的信息和资料也是很多的，首先判断下属于哪个文件系统，然后根据特定的文件系统格式自己分析的就可以的，其实这些方法的关键是怎么读和写的，读和写做到最底层，把读和写做好我想他检测文件功能是强大的。 <br /><br />够了，一些ARK的功能说到这就可以了，我希望各位搞RK的和ARK的人看了之后又会作出很多厉害，强大的东西来，希望看了之后会对各位有一点帮助的，希望可以在当前流行的RK和ARK中会有更新更强大的东西出现的，来激励我们学习和前进的，引用一位好友的话&ldquo;现在感觉大部分木马病毒什么的都是用的老一套东西的什么SSDT&nbsp;HOOK的。。。。。。，希望可以有些新的技术出现的&rdquo;，其实现在有些RK是很牛的，其实都是一个目标的&nbsp;希望<a href="http://www.3800hk.com/" class="channel_keylink">技术</a>和知识可以不断进步的&nbsp;嘿嘿。一个没有未来的人:）谈谈关于RK和ARK未来的发展&nbsp;RK&nbsp;更底层，ARK也更底层，攻和防，RK和ARK的斗争会继续的，RK会出现固化在某个文件里，会在重装系统后还会存在，会写到硬件中。。。。。。，ARK势必也需要对这些问题关注的。 <br /><br />谢谢各位看完文章的，本人一介小菜知识有限，以上是自己的一点愚见，如有什么错误和不足之处，请各位指教。 <br /><br />本文之中的有些知识是朋友和一些牛人给予帮助，谢谢他们的帮助。 <br /><br/>Tags - <a href="tag.php?tag=%E6%8A%80%E5%B7%A7" rel="tag">技巧</a> , <a href="tag.php?tag=%E5%AE%89%E5%85%A8" rel="tag">安全</a>
]]>
</description>
</item>
</channel>
</rss>