正则表达式的替换循环

时间:2017-04-27 10:13:31

标签: regex perl

我正在删除一些字符,例如我们不想从文本文件中获取的内容,这个正则表达式已经工作了很多年。

$content =~ s/[\xA0\x80\x93\xE2]//g

但是,我们现在有一个非常大的字符串来自一个文件(1.3Gig)它突然出现以下错误......

Substitution loop 

正则表达式看起来没问题,通过阅读错误和其他遇到同样问题的人,看起来可能存在一些硬编码的内部替换限制?

我使用的是Perl版本5.14.2

如果它刚刚达到硬编码限制,是否有任何解决方法,或者仍然有效的方法来达到不会达到此限制的目标?

2 个答案:

答案 0 :(得分:1)

当替换的迭代次数大于字符串中的字符数时,获得此错误。这绝不应该发生。我怀疑在使用无符号比较时使用带符号的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);

答案 1 :(得分:0)

您是否在文件中一次使用它?你可以尝试使用这种方法:

  1. 使用while循环
  2. 逐行读取文件
  3. 一次在一行使用正则表达式
  4. 将格式化文本写入新文件
  5. 请注意,我正在使用此方法处理大小约为5GB的文本文件。我的系统只有4GB RAM,效果很好。