正则基础之 小数点

一些细节
对于使用传统NFA引擎的大多数语言和工具,如Java、.NET来说,“.”的匹配范围是匹配除了换行符“\n”以外的任意一个字符。
但是对于javascript来说有些特殊,由于各浏览器的解析引擎不同,“.”的匹配范围也有所不同,对于Trident内核的浏览器,如IE来说,“.”同样是匹配除了换行符“\n”以外的任意一个字符,但是对于其它内核的浏览器,如Firefox、Opera、Chrome来说,“.”是匹配除了回车符“\r”和换行符“\n”以外的任意一个字符。

关于此细节的一些猜测


代码如下:

# <script type="text/javascript">
# document.write(/./.test("\r") + "<br />");
# document.write(/./.test("\n") + "<br />");
# </script>
# //IE下输出
# true
# false
# //Firefox、Opera、Chrome下输出
# false
# false

大概测了一下,Trident、Presto和Gecko应该都是采用的传统NFA引擎,而webkit至少是支持传统NFA引擎的,但是又与传统NFA引擎表现的不太一样,估计不是做了高级优化的传统NFA引擎,就是DFA/NFA混合引擎。
由于Windows下支持“\r”和“\n”,而UNIX下只支持“\n”,所以我猜想可能是由于其它浏览器引擎并不来自于Windows,所以没有提供对“\r”的支持,从而导致在正则中“.”也不匹配“\r”吧。没做深入研究,只是一些猜测罢了。
常见应用误区
注意
在匹配多行时,不要试图用“[.\n]”来匹配任意字符,这种写法表示的只是小数点和换行符两个字符中的一个,可以使用“(.|\n)”,但一般不这样用,这样写可读性差,效率也低,一般用“[\s\S]”,或者是用“.”加(?s)匹配模式来达到这一效果。

举例
需求描述:匹配<td>标签中的内容
源字符串:<td>This is a test line.
Another line. </td>
匹配结果:<td>This is a test line.
Another line. </td>
正则表达式一:<td>[\s\S]*</td>
正则表达式二:(?s)<td>.*</td>
匹配效率测试
以下为测试用字符串,即下面richTextBox1.Text里输入的内容(取自CSDN首页):


代码如下:

<link href="images/favicon.ico" rel="SHORTCUT ICON" />
<title>CSDN.NET - 中国领先的IT技术社区,为IT专业技术人员提供最全面的信息传播和服务平台</title>
<script language='JavaScript' type='text/javascript' src='http://www.csdn.net/ggmm/csdn_ggmm.js'></script> <script type="text/javascript" src="http://counter.csdn.net/a/js/AreaCounter.js%22%3E%3C/script>
<script type="text/javascript">

测试代码:


代码如下:

# string yourStr = richTextBox1.Text;
# StringBuilder src = new StringBuilder(4096);
# for (int i = 0; i < 10000; i++)
# {
# src.Append(yourStr);
# }
# string strData = src.ToString();
# List<Regex> reg = new List<Regex>();
# reg.Add(new Regex(@"[\s\S]"));
# reg.Add(new Regex(@"[\w\W]"));
# reg.Add(new Regex(@"[\d\D]"));
# reg.Add(new Regex(@"(.|\n)"));
# reg.Add(new Regex(@"(?s)."));
# string test = string.Empty;
# Stopwatch stopW = new Stopwatch();
# foreach (Regex re in reg)
# {
# stopW.Reset();
# stopW.Start();
# test = strData;
# test = re.Replace(test, "");
# stopW.Stop();
# richTextBox2.Text += "正则表达式:" + re.ToString().PadRight(10) + "执行时间:" + stopW.ElapsedMilliseconds.ToString() + " ms";
# richTextBox2.Text += "\n---------------------------------------\n";
# }

测试结果:
测试分两组进行,程序执行前内存占用为921M
一组是未使用量词,每次仅替换一个字符,执行时间如下,占用内存938M


代码如下:

正则表达式:[\s\S] 执行时间:2651 ms
---------------------------------------
正则表达式:[\w\W] 执行时间:2515 ms
---------------------------------------
正则表达式:[\d\D] 执行时间:2187 ms
---------------------------------------
正则表达式:(.|\n) 执行时间:2470 ms
---------------------------------------
正则表达式:(?s). 执行时间:1969 ms

另一组使用了量词,一次替换所有字符,执行时间如下,占用内存1128M


代码如下:

测试结果(带量词)
正则表达式:[\s\S]+ 执行时间:249 ms
---------------------------------------
正则表达式:[\w\W]+ 执行时间:348 ms
---------------------------------------
正则表达式:[\d\D]+ 执行时间:198 ms
---------------------------------------
正则表达式:(.|\n)+ 执行时间:879 ms
---------------------------------------
正则表达式:(?s).+ 执行时间:113 ms
---------------------------------------

测试结果分析:
匹配效率最高的是采用了Singleline这种匹配模式的“.”
其次是“[\d\D]”,而“(.|\n)”的匹配效率最低
“[\s\S]”的匹配效率居中,只是习惯上用得多些

注:由于各语言支持的引擎不同,即使使用同一种引擎,对正则做的优化也有所不同,所以以上性能测试结论可能仅适用于.NET。

(0)

相关推荐

  • 正则基础之 小数点

    一些细节 对于使用传统NFA引擎的大多数语言和工具,如Java..NET来说,"."的匹配范围是匹配除了换行符"\n"以外的任意一个字符. 但是对于javascript来说有些特殊,由于各浏览器的解析引擎不同,"."的匹配范围也有所不同,对于Trident内核的浏览器,如IE来说,"."同样是匹配除了换行符"\n"以外的任意一个字符,但是对于其它内核的浏览器,如Firefox.Opera.Chrome来说,

  • 正则基础之 \b 单词边界

    1概述 "\b"匹配单词边界,不匹配任何字符. "\b"匹配的只是一个位置,这个位置的一侧是构成单词的字符,另一侧为非单词字符.字符串的开始或结束位置."\b"是零宽度的. 基本上所有的资料里都会说"\b"是单词边界,但是关于"单词"的范围却是少有提及.通常情况下,正则表达式中所谓的"单词",就是由"\w"所定义的字符所组成的子串. "\b"表示所

  • 正则基础之 环视 Lookaround

    1       环视基础 环视只进行子表达式的匹配,不占有字符,匹配到的内容不保存到最终的匹配结果,是零宽度的.环视匹配的最终结果就是一个位置. 环视的作用相当于对所在位置加了一个附加条件,只有满足这个条件,环视子表达式才能匹配成功. 环视按照方向划分有顺序和逆序两种,按照是否匹配有肯定和否定两种,组合起来就有四种环视.顺序环视相当于在当前位置右侧附加一个条件,而逆序环视相当于在当前位置左侧附加一个条件. 表达式 说明 (?<=Expression) 逆序肯定环视,表示所在位置左侧能够匹配Exp

  • 正则基础之 NFA引擎匹配原理

    1       为什么要了解引擎匹配原理 一个个音符杂乱无章的组合在一起,弹奏出的或许就是噪音,同样的音符经过作曲家的手,就可以谱出非常动听的乐曲,一个演奏者同样可以照着乐谱奏出动听的乐曲,但他/她或许不知道该如何去改变音符的组合,使得乐曲更动听. 作为正则的使用者也一样,不懂正则引擎原理的情况下,同样可以写出满足需求的正则,但是不知道原理,却很难写出高效且没有隐患的正则.所以对于经常使用正则,或是有兴趣深入学习正则的人,还是有必要了解一下正则引擎的匹配原理的. 2       正则表达式引擎

  • 正则基础之 神奇的转义

    1 概述这或许会是一个让人迷惑,甚至感到混乱的话题,但也正因为如此,才有了讨论的必要.在正则中,一些具有特殊意义的字符,或是字符序列,被称作元字符,如"?"表示被修饰的子表达式匹配0次或1次,"(?i)"表示忽略大小写的匹配模式等等.而当这些元字符被要求匹配其本身时,就要进行转义处理了.不同的语言或应用场景下,正则定义方式.元字符出现的位置不同,转义的方式也是林林总总,不一而同.2 .NET正则中的字符转义2.1     .NET正则中的转义符绝大多数语言中,&qu

  • jQuery中的正则表达式分析 正则基础

    quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/ (?:-)表示是一个非捕获型 [^<]表示是以"<"起始,包含0个或多个'<'括号 (<[\w\W]+>)表示是一个捕获型,以'<>'起始,中间包含一个或多个字符 $表示字符的结尾 (#([\w\-]+))表示是一个捕获型,以'#'号和字符串.数字._以及-组成 rnotwhite = /\S/ \S表示是空白字符

  • 正则应用之 逆序环视探索 .

    1 问题引出 前几天在CSDN论坛遇到这样一个问题. 我要通过正则分别取出下面 <font color="#008000"> 与 </font> 之间的字符串 1.在 <font color="#008000"> 与 </font> 之间的字符串是没法固定的,是随机自动生成的 2.其中 <font color="#008000"> 与 </font>的数量也是没法固定的,也是

  • 正则匹配原理之 逆序环视深入 .

    说明:部分内容有待进一步研究和修正,因为最近工作太忙,暂时抽不出时间来,未研究过的可以跳过这一篇,想研究的不要被我的思路所左右了,有研究清楚的还请指正1 问题引出 前几天在CSDN论坛遇到这样一个问题: var str="8912341253789"; 需要将这个字符串中的重复的数字给去掉,也就是结果89123457. 首先需要说明的是,这种需求并不适合用正则来实现,至少,正则不是最好的实现方式. 这个问题本身不是本文讨论的重点,本文所要讨论的,主要是由这一问题的解决方案而引出的另一个

  • webregexp 正则测试实现代码

    WebRegExp 1.0 - 客服果果 [ 无忧版 ] body{background:#2B3C53;} *{font-size:12px;} #win{ width:900px;font-size:12px; position:absolute;left:0;top:0; background:#F1F0EA; border:2px outset;color:#000; -moz-border-top-colors:#d4d0c8 white; -moz-border-left-color

  • php用正则判断是否为数字的方法

    前两天朋友的一个网站上有人利用php注入提交flash游戏分数,后来找原因才发现是有一位参数没有做数字判断导致. 本来保存游戏分数是 game.php?ac=save&fgid=1这个形式来实现,在php网页里面fgid直接调用,没有做任何的过滤.很多人利用在fgid=1后面加一个字母(fgid=1a),来实现一些非法操作. 假如  gamlist table 里面有一个游戏  fgid为102 select gname from gamelist where fgid='102′; selec

随机推荐