正则表达式搜索一个非常大的文件

时间:2012-12-17 07:50:49

标签: ruby regex

我需要使用正则表达式扫描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

1 个答案:

答案 0 :(得分:5)

  1. 以块的形式遍历文件,而不是逐行遍历,其中块是由频繁出现的字符或模式(例如“X”)创建的。
  2. “X”是这样的,它在你的正则表达式中从不存在,即“X”是你的正则表达式永远不会与字符串匹配的地方。
  3. 在当前块中匹配正则表达式,提取匹配项并继续下一个块。
  4. 示例:

    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匹配数字多行, 然后,您可以选择一个块创建模式,而不是处理和加载整个文件,例如在这种情况下为.,并且只读取并处理直到此模式,然后移动到下一个块。

    CHUNK#1:

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

    CHUNK#2:

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

    等等。

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

      

    或者简单地阅读一些行,比如说20。当你找到了   匹配内,清除匹配结束并追加另外20行。   无需计算频繁出现的'X'。