Regex 来自正则表达式的替换循环
我正在从文本文件中剥离一些我们不想要的字符,比如bulletpoints,这个正则表达式已经工作了很多年Regex 来自正则表达式的替换循环,regex,perl,Regex,Perl,我正在从文本文件中剥离一些我们不想要的字符,比如bulletpoints,这个正则表达式已经工作了很多年 $content =~ s/[\xA0\x80\x93\xE2]//g 但是,我们现在从一个文件(1.3Gig)中得到一个非常大的字符串,它正在中断,并出现以下错误 Substitution loop 正则表达式看起来不错,从错误和其他有相同问题的人的阅读来看,看起来可能有一些硬编码的内部替换限制 我使用的是Perl版本5.14.2 如果只是降到硬编码限制,有没有办法解决这个问题,或者
$content =~ s/[\xA0\x80\x93\xE2]//g
但是,我们现在从一个文件(1.3Gig)中得到一个非常大的字符串,它正在中断,并出现以下错误
Substitution loop
正则表达式看起来不错,从错误和其他有相同问题的人的阅读来看,看起来可能有一些硬编码的内部替换限制
我使用的是Perl版本5.14.2
如果只是降到硬编码限制,有没有办法解决这个问题,或者有没有一种更有效的方法来达到同样的限制而不会达到这个限制?当替换的迭代次数大于字符串中的字符数时,就会出现这个错误。这永远不应该发生。我怀疑应该使用无符号比较时使用有符号32位比较。这可能已在较新版本的Perl中修复 对于该特定模式,您可以将字符串拆分为更小的字符串,或者可以使用更快的C函数来完成这项工作:
use Inline C => <<'__EOS__';
/* Limitation: Assumes all characters of the string are in 00..FF */
void clean(SV* sv) {
dXSARGS;
/* Need to use a "force" call when changing the buffer. */
STRLEN src_len;
char* src = SvPVbyte_force(sv, src_len);
STRLEN dst_len;
char* dst = src;
char* orig_dst = dst;
while (src_len--) {
switch ((unsigned char)*src) {
case 0x80:
case 0x93:
case 0xA0:
case 0xE2:
++src;
break;
default:
*(dst++) = *(src++);
}
}
dst_len = dst - orig_dst;
if (dst_len < SvLEN(sv))
*dst = '\0';
SvCUR_set(sv, dst_len);
SvSETMAGIC(sv);
XSRETURN_EMPTY;
}
__EOS__
clean($content);
使用内联C=>您是否在文件中立即使用它?您能否尝试使用这种方法:
使用while
循环逐行读取文件
每次使用一行正则表达式
将格式化文本写入新文件
请注意,我对5GB左右的文本文件使用这种方法。我的系统只有4GB的RAM,而且工作得很好。那么,$content
是1.3G的“原始”数据吗?它的内存可能要大一点。是的,这是一个很好的观点。我还不确定这个字符串在内存中到底有多少。我知道这个过程使用了6.8Gig,但是其中还有一些其他的数据结构,所以可能至少是一个Gig或者更少。服务器有16Gig内存,并且有一些空闲内存。我不确定为什么您的替代品会失败,但出于效率原因,我通常会非常小心将如此大量的内存直接“slurp”到内存中。是的,我同意,我们在另一个系统中有一个解决方案,我们不将所有内存加载到内存中以避免内存问题,但是,由于这只是一个文件,并且除了该错误之外不会导致任何问题,我想知道是否有一些不做太多更改的变通方法。下面是一个解释和提示:。(见消息底部)基本上,数字是硬编码的,并拆分字符串。