为什么使用ubuntu server的会被鄙视? 由于个人经历原因,我在06年经Dancefire推荐,才认识ubuntu的。时至今日,已有5、6年了。对着ubuntu有着莫名的喜爱。ubuntu桌面版的易用性,友好性,使得我这个菜鸟很容易的入门了。 如今,在公司的svn服务器系统选择上,我也选了ubuntu。 近期,重写了passport系统,出于好奇心,好奇自己的登录程序的并发处理能力、占用资源情况等,想压力测试一下,并不是项目真正完成的时候进行的测试。测试环境一切都是ubuntu的apt之后默认安装的配置。测试中发现瓶颈在DB,顺便让DBA帮看下哪里需要优化的。不想却被一位同事鄙视(善意的鄙视)一番,嘲笑我选择了ubuntu server。我很纳闷,我对linux不熟悉,找不到强有力的理由来反驳。不过,我觉得,不选择ubuntu的理由不能是向他所说的“哪有公司用ubuntu server?”。容我直白的说,如果真的这么想的话,我觉得这可能有些“井底之蛙”了。可能是ubuntu pc版本的界面,比较漂亮,安装软件更傻瓜化,点点鼠标的事情。软件的源很多,基本不用编译等等这些原因,认为使用ubuntu的人都是菜鸟级的。认为全是命令行的界面,所有软件都亲自编译那才叫高手。。。如果要是从内核上找优点,论证这些强项,我会更容易接受你的看法。 比起快速部署,我想,ubuntu server应该比centos之类redhat系的要快的多吧。至于觉得安装的没有编译的效率高,这些可以通过配置文件来设置吧。ubuntu更新比较频繁,可能在升级生,不会很平滑。 对于比较那种linux的server比较好的这种比较,就跟比较 asp.net、PHP、jSP、python等脚本语言比较牛B一样没有意义。更多的在于使用者,而不在于语言本身。如何选择,就看哪种自己更熟悉,更习惯。当然,我也是瞎扯了。我对linux基本不熟悉的。 顺便附上2011年-01-19的linux市场份额图: 其中,centos占了29%,ubuntu占了12.3%,也算不少了吧。 原文地址:http://w3techs.com/technologies/details/os-linux/all/all 2011-01-19 +10 14 0
apache RewriteMap MapSource自定义规则使用手记 10.1期间,一位朋友问我一个apache的 Rewrite规则中一个高级语法RewriteMap的用法问题。其想要实现的是这个功能,有个多用户的blog,用户访问的时候,是用三级域名访问的。比如http://cfc4n1.blog.cnxct.com,http://cfc4n2.blog.cnxct.com这种三级域名。在服务器上,是对三级域名做泛解析。每个三级域名都生成了一个静态的html主页文件。由于用户数量较多,linux ext硬盘格式上同一目录文件太多,检索文件的速度会有折扣,遂将文件打散到不同的目录下。打散方式是以用户名【三级域名中的cfc4n1,cfc4n2等】的MD5值的每隔两位作为一个目录。MD5的默认长度是32位,每隔两位分一次目录的话,那就有16级目录。每级目录的目录名是2个字符,每个字符的有16种可能【0-9a-f】,那么每级目录的目录数为256个目录,16级的话就有4096个目录。每个目录存1000个文件的话,可以存放4096000个文件,这样做,即可以把文件均匀打散到各个小目录中,同时,每个目录下的文件数又不是很多。当用户访问的时候,取目录里的用户名,计算MD5hash,做字符分割,重写到对应的目录下的文件中,如果文件不存在,则重写到生成这个文件的动态页面中。 到apache手册里找了下RewriteMap的用法 RewriteMap MapName MapType:MapSource 遂顺手在.htaccess里这么写了 然后访问一个三级域名试试。结果提示500 http 错误。到apache日志里看到如下 /var/www/.htaccess: RewriteMap not allowed here 搜了半天,不知道是什么错误,只好再次看手册,这时候,才发现rewritemap的作用域却是server config, virtual host,真汗了一下。自己没认真看手册。 改到virtual host里之后,重启apache,结果,还是http 500。再到错误日志里查个究竟。里面记录的确实(13)Permission denied: mod_rewrite: could not start RewriteMap program /var/www/1.php。呃,权限,权限。。赶紧chmod了一下。再次启动,却提示404。。。 /0a/c1/..../...html那种MD5字符串切割之后的文件找不到。但目录里确实是存在的啊。又到日志里查看,原来却是/0a/c1/...../...html\r 文件无法找到了。为什么地址后面多个\r呢?打开MapSource的脚本文件,才看到里面PHP操作流的结束字符里是“\r\n”了,去掉\r 才可以。 总结一下使用APACHE URL REwrite的RewriteMap方法要注意以下几点: 作用域-server config, virtual host,其他配置里无效。 自定义规则MapSource中流的结束符要跟操作系统符合,linux的要用“\n”,同时,切记在win平台编辑脚本传到linux上的时候,文件换行符要用linux格式的,不然,同样会出现问题。 要给apache赋予对脚本的读权限。 apache会在启动的时候,将自定义规则的脚本读取到内存中,之后,再次修改脚本时,不会立刻生效,需要重启 apache apache 的error.log中会记录[warn] mod_rewrite: Running external rewrite maps without defining a RewriteLock is DANGEROUS!这样的错误日志,在apache2.conf【我的系统是ubuntu,其他linux在httpd.conf中】中添加RewriteLock /etc/apache2/script/cfc.lock来指定RewriteLock的文件位置。记得给apache对script目录下有读写权限。 自定义脚本的代码格式如下: 2010-10-14 0 0
wordpress博客永久地址的二次重写 在很久很久以前,从前有座山,山上有个庙,庙里有个和尚在讲故事,讲什么呢? 从前有座山,山上有个庙,庙里有个和尚在讲故事,讲什么呢…… ...... 言归正传,很久以前,博客的URL是这种形式http://www.cnxct.com/cnxct/612/ 这种形式,后来呢,听网上SEOer说,为了更好的SEO,URL中包含关键词,可提高权重等等等等。遂打算把老的URL形式重写成hhttp://www.cnxct.com/%e6%88%91%e6%9c%80%e8%bf%91%e5%be%88%e6%b5%ae%e8%ba%81/这种形式。 服务器web services是nginx,需要更改如下规则 把/cnxct/数字/这种形式的老URL重写到/?p=数字这种形式,然后,Wordpress里在启用新的URL形式,让wordpress再把/?p=数字形式的URL再重写到目标URL。 效果如下图 一网友问到,遂共享出来 2010-09-25 +2 6 0
snoopy.class.php中_striplink方法的正则分析 上周提到老爷机坏了,昨天早上早早的抱去修理,维修工程师更换硬件排除法最后得知,故障出现在显卡,插入显卡,主板灯亮,按开关,没反映,或者CPU风扇抖动一下即停止。卸下显卡,开机正常。这位维修人员的结论是显卡坏了,建议更换显卡。我们有N卡9200,只要320元。我提出把显卡放到别的主机上试试,被拒绝了,好吧,那我也拒绝。最后,对方收我20元检测费。虽然我心里有点不情愿,他只是换了几个零件的简单排除法得出很有可能的结论而已,并没有告诉我准确的病因,是显卡的哪里出问题了?能否维修?他都没有告诉我。尽管这样,我还是给了,也没争论。 主机抱回来之后,自己卸下了显卡。开机,上网,打算到网上买块新的。老的显卡是我07年在学校买的。ATI RADEON X550,在当初,还算比较前卫的硬件。周五还赞扬其能勤奋工作到现在,而结果得知出问题的就是它。工作了3年多,不到四年,还能接收吧。主板换了华硕P5GC-MX/1333 ,作为硬件小白的我,也不知道换什么显卡较好。熟悉硬件的朋友,麻烦留言告诉一下,感谢了。现在打开网页,拉动浏览器滑动条的时候,卡的比较厉害,播放电影更是,像放映幻灯片一样。实在不能接受。遂网上搜了相关信息。价格在500左右。是有点贵了。遂暂时作罢。一整天心情都很低落,或者说,自从老爷机出问题了,心情一直很差。中午窝在家里,洗了洗衣服,趁太阳好,把冬天穿的衣服拿出来晒了晒。又挪动电脑附近的两个大桌子,打扫卫生,清理一番。一直忙到下午3点,头饿的晕忽忽的。匆忙到沙县小吃随便吃了点,下午,看会书,睡了会觉,早上送GF回家,起得太早了,困的厉害。睡醒之后,都7点多了,照照镜子,看看自己蓬松的发型,猥琐的样子,不禁笑了一笑。洗了把脸,到小区的理发店里剪了头发,由于是小区内,专门给老头老太太理发的,所以费用仅5元,在上海,应该没有比这还低了吧。晚上,把显示器接到电视盒上,看了会电视,差不多都是娱乐类的弱智脑残节目,我极为反感觉,又将显示器接回主机箱,开机到当当网上看了一番。因工作需要,要做个代码自动审计化的程序,我的想法是,不仅仅停留在对关键危险函数的正则匹配,而是做到语法分析,识别未初始化的变量、未过滤的富文本字段、SQL注入的方法等。想必,肯定的熟悉《编译原理》以及LEX、YACC之类相关知识,后悔大学没认真听,造成自己基础薄太弱了。当然,我也觉得大学的时候,直接教学生这么底层的知识没有循序渐进的引导学生去深入更好。可以从最简单的网页制作开始,然后,让学生对其感兴趣,再引导到动态,然后,联合数据库,然后效率优化,然后代码执行原理,然后编译原理类似这种步骤引导学生更好。比起现在的方式,可能更让学生感兴趣。(扯远了)东看西看,忙到了12点多才睡。 对于已经习惯8点左右起床上班的我来说,生物钟在早上8点左右,准时醒,有时候想赖床,但也无法再次入睡。起床洗漱,打开电脑,玩了两局web的三国杀,逛逛论坛,觉得饿了,才去煮点面条吃。回来继续,无意中打开PPC,看到一位网友“落叶人生”同学的帖子问一个正则问题,纠结了一下是否解释一下,以便给对方释疑解惑,也加固自己的知识。犹豫半天,觉得还是写下吧。下面正题: PPC链接http://bbs.phpchina.com/thread-189797-1-1.html preg_match_all("'<\s*a\s.*?href\s*=\s*([\"\'])?(?(1)(.*?)\\1|([^\s\>]+))[^>]*>?(.*?)</a>'isx",$document,$links); 对于一般的规范链 接能很好的使用,但不知道为什么对href=后面的网址不含引号的情况无法提取成功,哪个朋友帮分析下?谢谢! 其实,我没明白他的意思是想提取链接地址href后面的内容的,还是提取整个标签a中间的所有。 在下面的回帖中,他提到了这个正则来自snoopy.class.php的_striplink方法中的正则,遂到sf.net上下载一份原版到本地。 代码如下 先看下修饰符部分。【isx】,大家都知道【i】是不区分大小写;【s】是点号通配模式,也就是元字符【.】可以匹配换行符。在这里的作用是为了防止链接中出现换行的情况; 【x】宽松排列和注释模式,也就是空白字符不会被当成正则表达式的一部分,#后面的为注释,方便阅读的作用了。顺便说下括号后面的双引号后面的单引号,跟修饰符i前面的单引号,他们只是正则的起始标识,不是正则的一部分。其实,表达式里有单引号了,这里最好使用别的,比如斜杠,或者闭合的大括号等。 再看表达式【<\s*a\s.*?href\s*=\s*】,其后面也注释了,是匹配“<a href=”的,第一个【\s】匹配"<"到"a"之间的空白字符,不过一般都没的吧。都直接写"<a......"。后面的【\s】也是空白字符,不详细解释了。在后面的【.*?】是匹配“<a "到“href=”之间的内容,比如"title="....."、target="...."等。【href=】中没有元字符,就是匹配【href=】. 再后面【([\"\'])?】这里的单引号,双引号是被PHP语法转义的,真正的表达式是【(["'])?】,匹配单引号和双音号,并且,用小括号分配了组(整个表达式的第一组),后面有【?】量词,意味这可有可无。 再后面很重要了。去掉PHP的转义字符之后【(?(1) (.*?)\1 | ([^\s>]+)】,这是一个正则表达式的高级用法,叫“条件判断”表达式。语法为【(? if then| else)】。这里的if部分为【(1)】也就是前面说的“整个表达式的第一组”的内容,如果为真,则使用表达式【(.*?)\1】来匹配(\1是引用捕获的第一个组的内容),如果【(1)】没匹配到,则使用【([^\s>]+)】来匹配。这样,就可以实现没有引号的情况下,也是可以匹配到了。(正则表达式的条件判断语法,【|else】可以不写,表示不用else部分的表达式) 对于楼主的问题。应该怎么改?我刚刚刷新了帖子,看到楼主的正则是可以匹配的呀。 汗,贴下PHP的代码吧。 文章标题跟内容有很大出入,见谅哈。 2010-07-25 +4 8 0
PHP中正则表达式对UNICODE字符码的匹配 酷暑难耐,又在家宅一整天。天气热或许是借口,尽管不热,我也喜欢宅在家。晚上看新三国83集(插一句,最近世界杯很火,可是我不看世界杯。来鄙视我吧),一直看到10点半,突然觉得肚子痛,赶紧直奔厕所。如厕之后,觉得精神抖擞,容光焕发,年轻了二十多岁,打开QQ,看到N多条消息,其中有条是生命如蓝同学留的。打开一看,是PPC的链接,突然觉得我好久没登陆PPC了,想当年........算了,看链接吧。 打开链接,看到标题是“请教PHP 一个正则匹配的问题”,又是正则表达式,好吧,看下,谁让俺比较喜欢鼓捣正则呢。下面开始正题。 网友ainiaa的问题是 PHP代码如下 为什么打印的结果会是: otherStr: ! #$% & {}| '"你好啊我们 麻烦问下其中正则表达式 /[chr(128)-chr(256)]+/is 代表什么意思? 如果/[chr(128)-chr(256)]+/is 指的是ascii码在128到256的字符,为什么a-zA-Z这样的字符也被替换掉了,他们的ascii码是小于127的。 最令人郁闷的是为什么ascii码同在0-127区间"#","$","%","&", "!"," {","}","|"," '","确没有被替换掉???? 更令人感觉神奇的是 如果把正则表达式修改为"/[chr(128)-chr(256)]+/s"的话,输出的结果就变成了: otherStr: defg ijklmnopq stuvwxyz ! #$% & {}| '"你好啊我们 只是把正则表达式中的符号‘i’给去掉,结果缺失这样的。 完全的令我理解不了。 不知各位 有何见解???? 另附ascii 码 对照表 (这个ASCII码表的图我就不贴了) 回帖中,有个网友说没解析chr(128)这些,并给出了新的解决方法。首先说下此网友回答的是正确的,先不评论他是否“知其然,且知其所以然”,这位网友没有给出错误的原因。 CFC4N来回答一下这位网友: PHP的正则的preg_match函数用的是PCRE正则引擎,这位网友的代码中,PCRE引擎处理的正则表达式为【/[chr(128)-chr(256)]+/is】,后面的is是什么呢? 在PHP的正则里,边界字符后面的叫模式修饰符。它会告诉引擎如何解析,处理正则。其中i修饰符表示不区分大小写。s表示“点号通配模式”,用来让正则里的元字符点号【.】可以匹配换行符,这个修饰符仅对点号【.】起作用。在这位网友的问题中,修饰符s并不起作用的。 查找原因: 我们在来分析一下这个网友写的正则表达式【[chr(128)-chr(256)]+】,正则表达式的PCRE引擎是如何解释这个正则的呢?首先,我们要知道,在正则表达式中,中括号【[]】表示字符组,字符组中除了连接符【-】只外,都不是元字符,也就是说,都是普通字符,当然,如果连字符出现在第一个,或者不是标识两个字符之间范围的,都是普通的字符横杠“-”罢了。这里的chr(128)只是标识ASCII码为128(确切的说,ASCII码只是0-127个,128到其他的,应该不叫ASCII码了。),但是在正则里,他仍然代表【c、h、r、(、1、2、8、)】(顿号不是,只是区分易读的)这八个字符罢了。这个正则里的连接字符,是哪些范围呢?很明显,这里的连接字符的范围是【)-c】,“)”ASCII码为0x29,也就是十进制的41;“c”的ASCII码为0x63,也就是十进制的99,那么,他这个连接字符的范围就是ASCII 41(chr(41))到ASCII 99(chr(99))之间的字符。也就是说,这位网友的正则的范围是【[hr)-c(]】,就是chr(41)到chr(99)外加hr这两个字母和前面的“(”。 网友第一次测试的时候,有修饰符i,意思就是说,不区分大小写,那么在chr(41)到chr(99)之间的字符,以及这些字符如果有大小写,则包括他们的大小写都符合匹配。都会被替换成空。其第二次测试的时候,去掉了修饰符i,进行了不区分大小写的匹配,由于其范围只到c,但突然,再除了小写字母的“h”、“r”,所以,测试结果会多出“defgijklmnopqstuvwxyz”。所以,他的结果出现了这些差别。 网友的表达式等同于如下图所示 解决办法: 错误的原因找出来了,那么,解决的办法呢? 我们先来看看这位网友的需求,他的需求是将unicode(ASCII只是0-127位的,128之后的,应该叫UNICODE码)的chr(128)到chr(255)之间的字符匹配,替换为空罢了。正则表达式里,对十六进制的字符匹配的表示方式有两种,【\u】和【\x{}】,前者只能表示【\u】后面4位的十六进制数值,而后者【\x{}】则可以表示任意多的十六进制位数(写在大括号中)。 那么,这个正则表达式该如何写???? 网友的目的是chr(128)到chr(255),那么就是【[\u0080-\u00FF]】或者【[\x{0080}-\x{00FF}]】。 其目的是匹配下图中的红框内字符 提醒一下,PHP里正则匹配unicode字符时,需要使用u修饰符。 根据网友需求,更改正则之后的PHP代码如下: 其运行结果是仍然输出那段字符串,为什么呢?因为哪些字符串都不在chr(128)到chr(255)的范围之内。 (测试时,注意文件编码为UTF-8) 以上为鄙人愚见,欢迎批评指正。 2010-07-04 +2 6 0
升级ubuntu内核,virtualbox提示Kernel driver not installed (rc=-1908)出错 今天,我闲的蛋疼,更新来ubuntu内核,重启之后,也没在意,为了PS一张图,GIMP用起来不方便,遂开虚拟机virtualBox,进XP,用PhotoShop来操作,结果,VirtualBox却提示“ernel driver not installed (rc=-1908)”,我还没来得及点确定,又提示 The VirtualBox Linux kernel driver (vboxdrv) is either not loaded or there is a permission problem with /dev/vboxdrv. Re-setup the kernel module by executing '/etc/init.d/vboxdrv setup' as root. Users of Ubuntu, Fedora or Mandriva should install the DKMS package first. This package keeps track of Linux kernel changes and recompiles the vboxdrv kernel module if necessary. 好吧,我照办,开中端,敲入sudo /etc/init.d/vboxdrv setup,回车,立马提示 屏幕停止在“Recompiling VirtualBox kernel module ”半天没反映,我有点心慌来,赶紧搜下。等到我切换到终端看结果的时候,却发现提示“* Starting VirtualBox kernel module * done.”,我 草,好了。那好吧,打开虚拟机看看,进XP。。。OK,正常了。。 附截图一张。 至于这个错误是什么原因导致的,等我下次蛋疼的时候,再去查明真相吧。 2010-06-21 +1 5 0
PHP正则表达式的效率:回溯与固化分组 上文中,我们聊到了一点关于PHP中(NFA PCRE)正则表达式匹配优先量词,忽略优先量词的匹配原理了。那么上文留下的问题,您的答案是什么呢? 先来看下问题。 字符串 正则表达式为 这三个正则,分别会造成几次回溯呢?? 答案: 对于第一种贪婪匹配的匹配规则,回溯的9次是正则【】对字符串“”匹配时,构成的回溯,回溯的次数,恰好是字符串的长度。 第二种非贪婪匹配规则,回溯5次,是正则【.+?】对字符串“123456”匹配时构成的回溯。回溯的次数,为字符串长度减去最小次数。也就是6-1=5次。如果正则表达式为【.*?】那么,回溯次数就是6次了。 第三种正则是零宽断言,或者叫环视。(暂且不说。) 在NFA正则引擎中,回溯是他的灵魂,所以,不管是贪婪,非贪婪,环视等写法中肯定会有回溯的出现的,这个我们无法避免(用词不太准确),但是,我们可以减少回溯的次数,或者保护其中一部分匹配的规则不进行回溯。 对于上篇BLOG上提到的鸟哥谈到一个非贪婪引起的大量回溯问题,大家可以知道,回溯,确实是浪费资源的罪魁祸首,那么,我们能否不让其回溯呢? 答案是肯定的,NFA引擎中,有个概念,叫固化分组。引用一下书上的概念 具体来说,使用「(?>…)」的匹配与正常的匹配并无差别,但是如果匹配进行到此结构之后(也就是,进行到闭括号之后),那么此结构体中的所有备用状态都会被放弃。也就是说,在固化分组匹配结束时,它已经匹配的文本已经固化为一个单元,只能作为整体而保留或放弃。括号内的子表达式中未尝试过的备用状态都不复存在了,所以回溯永远也不能选择其中的状态(至少是,当此结构匹配完成时,“锁定(locked in)”在其中的状态)。 那么,固化分组到底有什么用处呢?我们来举个例子。(找不到合适的例子,俺只好借用一下书上的例子了) 比如要处理一批数据,原来格式为123.456,后来因为浮点数显示问题,部分数据格式变为123.456000000789这种,,要求做到只保留小数点后面2-3位,但是,最后一位不能为0,这个正则如何写呢?(下面直接考虑小数点后面的数字),写出正则之后,我们还要用这个正则去匹配数据,把原来的数据替换成匹配的结果。 首先,我们可以立刻写出这样的正则【\.\d\d[1-9]?\d*】,PHP代码为 很明显,这种写法,对于部分数据格式为123.456的这种格式,白白的处理了一遍,为了提高效率,我们还要对这个正则进行处理。从123.456这个字符串跟其他的比较一下,我们发现,是疑问123.456这个数据后面没数字了,所以,白白处理一遍。那好办,我们对这个正则改造一下,把后面的量词*改成+,这样对于123.45 小数点后面1,2位数字的,不会去白白处理,而且,对三位以上数字的,处理正常。其PHP代码为 好了,这个正则真的没问题吗??确定吗?上篇博文,我们了解了匹配原理,那么,我们也分析一下这个正则的匹配过程吧。 字符串"123.456",正则表达式为【\.(\d\d[1-9]?)\d+】,我们来看下 首先(小数点前123不说了),【\.】匹配".",匹配成功,把控制权给下一个【\d】,【\d】匹配“4”成功,把控制权给第二个【\d】,这个【\d】匹配“5”成功,然后,把控制权给了【[1-9]?】,由于量词是【?】,正则表达式遵循“量词优先匹配”,而且,此处是【?】,还会留下一个回溯点。然后匹配"6"成功,然后把控制权给【\d+】,【\d+】发现后面没字符了,最遵循“后进先出”规则,回到上一个回溯点,进行匹配,这时,【[1-9]?】会交还出其匹配的字符“6”,【[1-9]?】匹配“6”成功。匹配完成了。大家发现【(\d\d[1-9]?)】匹配的结果确是"45",并不是我们想要的“456”,“6”被【\d+】匹配去了。那么,我们该如何办呢? 能否让【[1-9]?】匹配一旦成功,不进行回溯呢?这就用到了我们上面说的"固化分组", PHP(preg_replace函数)中使用的正则引擎支持固化分组,我们根据固化分组的写法,可以把代码改成如下方式 改成这样的话,那字符串“123.456“是不符合要求,不会被匹配的。那我们就可以实现我们的要求了。 从上面的例子中,知道了固化分组的作用,那么对于鸟哥BLOG上写的那个非贪婪的回溯问题,我们能否也对其改造,使得其不回溯呢? 先看下鸟哥给的答案 鸟哥写的很精悍。排除“ 2010-06-21 +10 14 0
小议正则表达式效率:贪婪、非贪婪与回溯 前几天看了鸟哥的BLOG上写的关于正则表达式的回溯与递归的限制时,对贪婪、非贪婪产生的回溯有疑问,遂近段时间,仔细的学习研究了一下,现在把经验心得与大家分享一下。 (我日,这里好像被左侧的图挡着了,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数,换行换行凑字数) 先扫盲一下什么是正则表达式的贪婪,什么是非贪婪?或者说什么是匹配优先量词,什么是忽略优先量词? 好吧,我也不知道概念是什么,来举个例子吧。 某同学想过滤之间的内容,那是这么写正则以及程序的。 看起来,好像没什么问题,其实则不然。若 那么经过上面的程序处理,其结果为 仍然达不到他想要的效果。上面的就是非贪婪,也有的叫惰性。其标志非贪婪的标识为量数元字符后面加? ,比如 +?、*?、??(比较特殊,以后的BLOG中,我会写到)等。即标识非贪婪,如果不写?就是贪婪。比如 以上为贪婪,非贪婪的区别介绍。下面,聊下贪婪、非贪婪引起的回溯问题。先看个小例子。 正则表达式为\w*(\d+),字符串为cfc456n,那么,这个正则匹配的$1是多少?? 如果您回答是 456,那么,恭喜你,回答错了,其结果不是456,而是6,您知道为什么吗? CFC4N来解释一下,当正则引擎用正则\w*(\d+)去匹配字符串cfc456n时,会先用\w*去匹配字符串cfc456n,首先,\w*会匹配字符串cfc456n的所有字符,然后再交给\d+去匹配剩下的字符串,而剩下的没了,这时,\w*规则会不情愿的吐出一个字符,给\d+去匹配,同时,在吐出字符之前,记录一个点,这个点,就是用于回溯的点,然后\d+去匹配n,发现并不能匹配成功,会再次要求\w*再吐出一个字符,\w*会先再次记录一个回溯的点,再吐出一个字符。这时,\w* 匹配的结果只有cfc45了,已经吐出6n了,\d+再去匹配6,发现匹配成功,则会通知引擎,匹配成功了,就直接显示出来了。所以,(\d+)的结果是6,而不是456。 当上面的正则表达式改为 \w*?(\d+)(注意,此处为非贪婪),字符串仍然为cfc456n,那么,这时候,正则匹配的$1是多少?? 甲同学回答:结果是 456。 嗯,是的,正确,是456,CFC4N弱弱的问下,为什么是456 呢? 我在来解释一下 为什么是456 正则表达式有条规则,是量词优先匹配,所以\w*?会先去匹配字符串cfc456,由于\w*?是非贪婪,正则引擎会用表达式\w+?每次仅匹配一个字符串,然后再将控制权交给后面的\d+去匹配下一个字符,同时,记录一个点,用于在匹配不成功的时候,返回这里,再次匹配,也就是回溯点。由于\w后面是量词是*,*表示0到无数次,所以,首先是0次,也就是\w*?匹配个空,记录回溯点,将控制权交给\d+,\d+去匹配cfc456n的第一个字符c,然后,匹配失败,于是乎,接着讲控制权交给\w*?去匹配cfc456n的c,\w*?匹配c成功,由于是非贪婪,所以,他每次只匹配一个字符,记录回溯点,然后再将控制权交给\d+匹配f,接着,\d+匹配f再失败,再把控制权给\w*?,\w*?再匹配c,记录回溯点(这时\w*?匹配结果是cfc了),再把控制权给\d+,\d+去匹配4,匹配成功,然后,由于量词是+,就是1到无数次,所以,接着往后匹配,再匹配5,成功,再接着,再匹配6,成功,再接着,继续匹配操作,下一个字符是n,匹配失败,这时,\d+会吧控制权交出去。由于\d+后面已经没有正则表达式了,所以,整个正则表达式宣告匹配完成,其结果就是 cfc456, 其中第一组结果是456。亲爱的同学,您明白刚刚的题目的结果,为什么是456了吗? 好了,您是否从上面的例子了解了贪婪,非贪婪的匹配原理了?那您是否明白您在什么时候需要使用贪婪,非贪婪去处理您的字符串了? 鸟哥的文章里讲到针对 表达式、程序为 其原因就是回溯太多了,直到造成耗尽栈空间爆栈。 再来看个例子。 字符串 正则表达式为 这三个正则,分别会造成几次回溯呢?? 答案见下篇 PHP正则表达式的效率:回溯与固化分组 2010-06-18 +8 12 0
端午节之后一周总结 本周主题:瞎扯淡。 记下本周(确切的说,是上周)流水账: 在当当网上买了本书《精通正则表达式》,送货速度很快,前天晚上下的订单,第二天中午就送到了。值得表扬。 姐姐来我这玩,带来了一点粽子,蜜枣馅的,还有煎饼等家乡的特产,非常感谢。 陪小外甥再次看了《汽车总动员》,!@#¥#%%¥……¥&%……*…… CNXCT.COM域名已经到期,忘记续费了,还好,GLEON同学没忘记,悄悄的续费了。 端午在家看了新买的书《精通正则表达式》,直接从第四章匹配原理开始看,因为我买书的主要原因是想知道匹配原理。还有就是仔细的看了在非贪婪、贪婪的情况下,匹配时候的回溯详情,匹配的优先顺序,回溯的次数,效率等情况。致力做到不光写得出正则,还要写的出高效率的正则表达式 最近比较懒,从过年回来,基本没运动过,上上上周,打了羽毛球。总共运动时间大约20分钟,其中,大部分时间是捡球,羽毛球老是被我抽到树枝上。想办法把羽毛球取下来,也是件麻烦事。周围没有很长的竹竿,树枝之类东西,只好从地上捡起石块砸。结果,右手胳膊酸了一周。昨天,跟几个朋友一起打升级。由于右手一直轻轻的拿鼠标,没有那么用力的捏牌,结果,今天胳膊又酸了。CFC4N想弱弱的问,难道打升级也算运动? 昨天,把床上铺的床单取掉了,直接躺在竹席上,结果,夜里肚子被冰的很痛,一夜没睡好,结果,现在精神状态很差。 今天看到还算是比较轰动的IT新闻,马化腾马云收编草根网站 互联网大佬争夺站长,新闻的主要内容是腾讯收购草根的IT公司康盛创想,其主打产品是Discuz!,不知道是真还是假。很多网友都调侃说到“期待使用’QQ PassPort‘登陆各大BBS”,我稍微想了一下,如果实现,应该也不难。CFC4N想了一个方案,各位网友来批评指正一下。 腾讯可以做一个系统,各大论坛使用者提交论坛的主域名,腾讯再根据论坛使用者的主域名分配一个私钥,然后,论坛使用者将此私钥更改到论坛程序的认证部分文件中。当用户在其中的论坛用QQ登陆的时候,直接跳转到腾讯的登陆页,登陆成功之后,返回到用户登陆前的论坛,论坛再根据私钥来解密cookie,来判断此cookie是否生效。 无意中发现google对我们的BLOG www.cnxct.com 的快照更新了,而某度却还是那样。详情见下图 呃。差点忘了,刚刚从QQ网络硬盘里,找出N年前收藏的工具SPXInstantScreenCapture,试用截图了,效果就是上图。其中,百度截图那张,有水印。原因是没注册,其实我有别人的注册码,只是我没用,打算中午用OD自己破解一下,很久不搞,基本的反汇编工具都生疏了。温习一下。 2010-06-17 1 0
coolcode转SyntaxHighlighter与Mysql正则表达式 blog的代码高亮插件原来是coolcode的,coolcode的高亮插件确实很酷,显示效果也很棒,但是占用的位子太大了。最近,我抽空改成SyntaxHighlighter。由于coolcode插件的开头标签是或者[coolcode]这样的,而SyntaxHighlighter是这样的(或者其他)。遂只能想办法把老的格式转化成新的格式。当然,肯定用到正则表达式了。 原来的代码高亮开头标识为 这种类型的, 而SyntaxHighlighter的标识为 那根据要求写的正则表达式为 解释一下 [a-z]+ 匹配 php,javascript,cpp,sql,css 等,后面的.*?中的 .表示任何除了换行之外的字符,而*表示0次或者无数次,*+这些表述次数的符号后面接的?标识非贪婪模式 看图,这个正则可以实现上述要求了。 但是,问题还没解决,我们还有一种情况没考虑,那就是后面不一定接的就是lang="php"这样的属性啊,有可能是download,也有可能是linenum="on/off"啊,所以,我们的正则还需要改。 CFC4N把正则改为 截图如下 细心的朋友可能看出来图中匹配的红色框内多出了,意思也就是说,前面的需要排除掉。如何排除呢?聪明的你肯定立刻想到.这个万能字符替换成非两个符号的规则,好,CFC4N立刻修改一下。 修改之后的正则为 果然,匹配正常了。结果见截图。 到这里,问题似乎解决了,可是,当初糊涂的我,把coolcode的两种开头标识都用了,那就是和[coolcode,那么,看官您认为这个正则该如何改写呢? 没错,无非就是开头,结尾的标识考虑两种情况 2010-06-02 +2 6 0