0

我使用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 次。

4

1 回答 1

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.3s;1m 53.9s 1024 行)。

出于比较的目的,我收集了一些放在测试目录中的 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

是的,您可以拒绝任何提交审查的包含此类评论的代码。

于 2012-09-08T15:07:58.087 回答