周末记事-还是我的老爷机

我的老爷机:
06年买的主机箱+飞利浦CRT显示器,07年更换电源风扇,08年上半年分别更换了主板,硬盘,下面年,在内存最低价的时候,99块包快递买了DDR2 667的内存条一根,更新了老内存。09年再次更换了电源风扇,10年由于换地方住,搬家,桌子太靠墙,CRT大屁股显示器放不下,买了优派的22寸液晶显示器,鸟枪换炮了,哈。CRT显示器忍痛割爱以50元的价格卖给了小贩,哎,心痛。接着,鼠标又不灵了,更换了鼠标。从06年坚守到现在的器件只有CPU、主机箱、显卡,光驱、键盘了。

昨天晚上,10点半左右,老爷机又突然间罢工了,顿时,我心急如焚呀,心想即将到来的周末,作为宅男,我不能接受。赶紧调试吧。首先,我以为是天气太热,导致CPU温度过高,激活主板自动保护策略,强制关机的。赶紧把CPU风扇拿出来,放到空调边吹了会,装上去之后,开机,还是不行,主板灯亮了,但是CPU风扇不转,而且,电源也没反映,我愕然了,难道电源又坏了不成?好吧,我认输,周末再说吧,睡觉。

前序:
在老爷机罢工之前,一群内网友求助正则匹配html标签中 table之间的内容,要发现的第一个table之间的内容。字符串大约为

<table class="t1 t2"><tr><td><table class="t1 t2">sssssssssssssssss</table></td></tr><tr>
<td><table class="t1 t2">ss
sssssssssssssss</table></td></tr></table>

同学A提供【<table[\s\S]*</table>】(具体记不清了,大体是这个)

这个正则的匹配结果是不能满足其要求的,很明显,【*】为量词优先,导致贪婪匹配把后面最后一个</table>之前的字符串全部匹配进去了。

见截图:

A同学提供的不严谨的正则表达式

接着,另外以为网友提到,后面加U修饰符。对于这个正则,对于这个要求,加U修饰符能达到目的吗? 答案是可以的。为什么?这种方式可靠吗?有风险吗?有其他方法吗?

先来解释一下U(大写字母U,非小写,小写的是uincode字符模式)是干吗的? 是对“匹配优先量词(贪婪)”与“忽略优先量词(非贪婪)”的取反,也就是说,原来是【*】、【+】的,会按照【*?】、【+?】来执行,如果是【*?】、【+?】的,则按照【*】、【+】来执行,这个修饰符很怪,很乱,如果正则为【\w+】,为了达到“非贪婪匹配”,使用了修饰符U。过几天,你修改了这个正则,修改为【\w+\s+?】,你的本意是在原来的基础上,加上非贪婪的空白字符的匹配,可是,后面的大写字母U修饰符也对你前面的非贪婪取反了,从而,导致匹配错误,所以,建议大家不要使用大写字母的U修饰符,直接在表达式里写好贪婪还是非贪婪。

我的答案是【<table[^>]+?>(?>((?!</table>).(?<!<table))+)</table>】。

我靠,你这这什么玩意?这么乱?这是什么意思?

解释一下:

  1. 【<table[^>]+?>】部分是匹配“<table class=”t1 t2″>”这种table的开头,包括属性的字符串,其中,使用了忽略优先量词(非贪婪),由于其属性不会太多,常规下不超过50个字符串,所以,没有使用固化分组,或者占有优先量词来减少回溯。
  2. 【</table>】(最后面的)是匹配字符串结束的。不用解释了吧。
  3. 【(?>((?!</table>).(?<!<table))+)】这个比较长,主要是匹配<table….到</table>中间的字符串,其中最外面一层【(?>)】是占有优先量词,用来防止不必要的回溯,防止中间超长的字符串造成崩溃。【(?!</table>)】是顺序零宽断言非操作,匹配位置,针对其后面的规则【.】,意思就是说,规则【.】后面不能是字符串“</table>”,同样正则【(?<!<table】是逆序零宽断言非操作,也匹配位置,针对其前面的规则【.】,意思就是说,规则【.】前面不能是字符串“<table…”,这样,两个零宽断言来确定一个字符串,如果是多个字符串,则加上匹配优先量词【+】,但是这个【+】的位置要注意了,不能直接放在【.】的后面,因为要保证每个【.】匹配的字符串,前后的规则都符合两个零宽断言,则需要放在外面,也就是上面所写的那样。

OK,解释完毕,你明白了没?如果没,那是我的错。请留言,批评,我承认错误。(当使用匹配的时候,为了更准确,建议开启不区分大小写模式,以及,多行匹配模式,即修饰符i和修饰符s,小写的s,不是大写的,大写的S是另外的含义<以后写>。)

见截图:

相对比较严谨,比较准确的正则表达式

测试代码:

$str='111<table class="t1 t2"><tr><td><table class="t1 t2">sssssssssssssssss</table></td></tr><tr>
<td><table class="t1 t2">ss
sssssssssssssss</table></td></tr></table>ssss';
preg_match_all('%<table[^>]+?>(?>((?!</table>).(?<!<table))+)</table>%si', $str, $result, PREG_PATTERN_ORDER);
print_r($result[0]);

我的答案可以解决问题吗?可以。准确吗?还行,不太准。为什么?如果table中间有嵌套,则无法正确匹配。如何修复?正则递归匹配。如果递归?

留给你研究吧。CFC4N小试正则表达式里已经介绍了一个关于递归匹配的例子,你可以参考一下。

后续:

老爷机挂了,我一夜没睡着,早上6点10分就醒了,起来之后,捣鼓两下,也没心情了,已经知道大体的症状。手头没工具,也没法测试,算了,索性洗漱去公司。走的早也好,地铁上没多少人,一路不拥挤,唯一的缺点就是没拿到“时代报”。不过到了公司楼下,有派发的,顺手拿了一份。到座位上,心思还在我心爱的老爷机上,也有重新买台新机器的想法,到DELL官方网站上搜了几下,发现价格奇贵,光主机,都4K-5K,看了一会,我就大小这个念头了,作为寄生在这大城市的P民,也别要求太高了。讲究用吧。哎,打算周末冒热抱出去找维修铺,各位,祝福我吧。

PS:下午,拿了早上没看的报纸去厕所,心想,这次终于不干等了,可以打发时间了。当我到厕所里的时候,我震惊了,我靠,马桶上起码5份报纸,而且,还都不一样。汗。

您可能喜欢下面几篇博文

发表评论

4 Comments.

  1. - -祝福你早日修好老爷机。 :grin:

  2. 哈~你的CRT显示器只卖了一半的价格哦

  3. nflauthentic

    老爷机折腾的怎么样了啊

Leave a Reply



[ Ctrl + Enter ]

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

Trackbacks and Pingbacks:

CNXCT小组的博客 is Stephen Fry proof thanks to caching by WP Super Cache