5

我需要用正则表达式扫描一个 300MB 的文本文件。

  • 读取整个文件并将其放入变量中会占用超过 700MB 的 RAM,然后因“无法分配内存”错误而失败。
  • 匹配可以是两行或三行,所以我不能在循环中使用行到行步进。

是否有任何惰性方法可以使用正则表达式进行完整文件扫描而不将其读入单独的变量?

UPD

完毕。现在您可以使用此功能按块读取。为您的目标修改它。

def prepare_session_hash(fname, regex_string, start=0)
  @session_login_hash = {}
  File.open(fname, 'rb') { |f|
    fsize = f.size
    bsize = fsize / 8
    if start > 0
      f.seek(start)
    end

    overlap = 200

    while true
      if (f.tell() >= overlap) and (f.tell() < fsize)
        f.seek(f.tell() - overlap)
      end
      buffer = f.read(bsize)
      if buffer
        buffer.scan(s) { |match|
          @session_login_hash[match[0]] = match[1]
        }
      else
        return @session_login_hash
      end
    end
  }
end
4

1 回答 1

6
  1. 以块的形式遍历文件,而不是逐行遍历文件,其中块是由频繁出现的字符或模式的出现创建的,比如“X”。
  2. “X”是这样的,它永远不会存在于您的正则表达式中,即“X”是您的正则表达式永远不会匹配字符串的位置。
  3. 在当前块中匹配您的正则表达式,提取匹配项并继续下一个块。

例子:

This is string with multline numbers -2000
2223434
34356666
444564646
. These numbers can occur at 34345
567567 places, and on 67
87878 pages . The problem is to find a good
way to extract these more than 100
0 regexes without memory hogging.

在本文中,假设所需的模式是数字字符串,例如/d+/s匹配数字多行,那么您可以选择一个块创建模式,而不是处理和加载整个文件,在这种情况下说 FULL STOP.并且只读取和处理直到该模式,然后移动到下一个块。

块#1:

This is string with multline numbers -2000
2223434
34356666
444564646
.

块#2:

These numbers can occur at 34345
567567 places, and on 67
87878 pages

等等。

编辑:也从评论中添加@Ranty的建议:

或者简单地阅读一些行数,比如 20 行。当您在其中找到匹配项时,清除匹配项并附加另外 20 行。无需计算频繁出现的“X”。

于 2012-12-17T08:05:59.967 回答