我使用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次。
我怀疑问题的部分原因是您的"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
我没有得到核心转储(MacOSX10.7.4上的Perl5.16.0;8GiB主内存)。这确实需要相当长的时间。当它在运行时,它没有生长;在1024行运行期间,它使用了大约13 MiB的"真实"内存和23 MiB的虚拟内存。
我尝试了Perl5.10.0(我在机器上编译过的最旧版本),它使用的"真实"内存略少,基本上是相同的"虚拟"内存,而且速度明显较慢(512为33.3s线1m 53.9s(1024行)。
为了进行比较,我收集了一些放在测试目录中的C代码,创建了一个大约88 KiB的文件,其中3100行是注释行。相比之下,数据1024文件的大小约为77KiB。处理时间在10到20毫秒之间。
摘要
您所拥有的非C源代码是一个非常糟糕的测试用例。Perl不应该崩溃。
您正在使用哪个版本的Perl,在哪个平台上使用?你的机器有多少内存。然而,内存总量不太可能成为问题(在大多数运行Perl的机器上,24MiB不是问题)。如果您有一个非常旧的Perl版本,结果可能会有所不同。
我还注意到正则表达式不处理C编译器必须处理的一些病态的C注释,例如:
/
* Yes, this is a comment *
/
/
/ And so is this
是的,您可以拒绝任何包含此类评论的提交审查代码。