改进正则表达式以匹配javascript注释

时间:2012-09-08 14:03:27

标签: regex perl segmentation-fault

我使用perlfaq6中给出的正则表达式来匹配和删除javascript注释,但是当字符串太长时会导致分段错误。正则表达式是 -

s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//([^\\]|[^\n][\n]?)*?\n|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $3 ? $3 : ""#gse;

可以改进以避免分段错误吗?

[编辑]

长输入:

<ent r=\"6\" t=\"259\" w=\"252\" /><ent r=\"6\" t=\"257\" w=\"219\" />

重复了大约1000次。

1 个答案:

答案 0 :(得分:3)

我怀疑问题部分在于你的“C代码”与C代码不太相似。例如,在C中,您不能将序列\"放在一对引号之外,例如单引号或双引号。

我修改了正则表达式,使其可读并包装成一个琐碎的脚本,其中输入并将正则表达式应用于它:

#!/usr/bin/env perl

### Original regex from PerlFAQ6.
### s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//([^\\]|[^\n][\n]?)*?\n|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $3 ? $3 : ""#gse;

undef $/;  # Slurp input

while (<>)
{
    print "raw: $_";

    s%
        /\*[^*]*\*+([^/*][^*]*\*+)*/    # Simple C comments
     |  //([^\\]|[^\n][\n]?)*?\n        # C++ comments, allowing for backslash-newline continuation
     |  (
            "(\\.|[^"\\])*"             # Double-quoted strings
        |   '(\\.|[^'\\])*'             # Single-quoted characters
        |   .[^/"'\\]*                  # Anything else
        )
     %    defined $3 ? $3 : ""
     %egsx;

    print "out: $_";
}

我接受了你的非C代码行,并创建了文件data.1,data.2,data.4,data.8,...,data.1024,每行中包含适当的行数。然后我运行了一个定时循环。

$ for x in 1 2 4 8 16 32 64 128 256 512 1024
> do
>     echo
>     echo $x
>     time perl xx.pl data.$x > /dev/null
> done
$

我已经输出了输出,只给出了不同文件大小的实时时间:

   1    0m0.022s
   2    0m0.005s
   4    0m0.007s
   8    0m0.013s
  16    0m0.035s
  32    0m0.130s
  64    0m0.523s
 128    0m2.035s
 256    0m6.756s
 512    0m28.062s
1024    1m36.134s

我没有获得核心转储(Mac OS X 10.7.4上的Perl 5.16.0; 8 GiB主内存)。它确实需要花费大量时间。它在运行时却没有增长;在1024线运行期间,它使用了大约13 MiB的“真实”内存和23 MiB的“虚拟”内存。

我尝试过Perl 5.10.0(我在我的机器上编译的最旧的版本),它使用的“实际”内存略少,基本上是相同的“虚拟”内存,而且速度明显变慢(512为33.3秒) 线; 1024线的1米53.9秒。

为了便于比较,我收集了一些我在测试目录中存在的C代码,以创建大约88 KiB的文件,其中3100行,其中大约200个是评论行。这与data.1024文件的大小相比,大约是77 KiB。处理时间在10到20毫秒之间。

摘要

你拥有的非C源代码是一个非常讨厌的测试用例。 Perl不应该崩溃。

您使用的是哪个版本的Perl,以及在哪个平台上?你的机器有多少内存。但是,内存总量不太可能成为问题(在运行Perl的大多数计算机上,24 MiB不是问题)。如果你有一个非常旧版本的Perl,结果可能会有所不同。


我还注意到正则表达式不处理C编译器必须处理的一些病态C注释,例如:

/\
\
* Yes, this is a comment *\
\
/
/\
\
/ And so is this

是的,您拒绝提交包含此类评论的任何提交审核的代码是正确的。