2014-01-21 25 views
0

我有一个很大的文本文件,我从中提取URL。如果我运行:为什么节点不能处理这个正则表达式,但Python可以?

import re 

with open ('file.in', 'r') as fh: 
    for match in re.findall(r'http://matchthis\.com', fh.read()): 
     print match 

它运行在一秒钟左右的用户时间,并得到我想要的网址,但如果我运行这些:

var regex = /http:\/\/matchthis\.com/g; 
fs.readFile('file.in', 'ascii', function(err, data) { 
    while(match = regex.exec(data)) 
     console.log(match); 
}); 

OR

fs.readFile('file.in', 'ascii', function(err, data) { 
    var matches = data.match(/http:\/\/matchthis\.com/g); 
    for (var i = 0; i < matches.length; ++i) { 
     console.log(matches[i]); 
    } 
}); 

我得到:

FATAL ERROR: CALL_AND_RETRY_0 Allocation failed - process out of memory 

发生了什么事与node.js正则表达式引擎?有什么办法可以修改东西,使他们在node中工作?

编辑:误差似乎是fs中心因为这也产生错误:

fs.readFile('file.in', 'ascii', function(err, data) { 

}); 

file.in约为800MB。

+1

'file.in'里有什么?你能做出一个可重复的例子吗?另外,'http:// matchthis.com'没有正确转义。你需要逃避这段时间。 – Blender

+0

@Blender固定了'\ .'我错过了,因为我输入了问题。 'file.in'是1400000行ascii文本,其中包含各种文本片段中的URL。 – bqui56

+0

@Blender不应该在Python中固定点吗? – thefourtheye

回答

2

你应该处理由使用流式文件接口行的文件行。事情是这样的:

var fs = require('fs'); 

var byline = require('byline'); 

var input = fs.createReadStream('tmp.txt'); 
var lines = input.pipe(byline.createStream()); 

lines.on('readable', function(){ 
    var line = lines.read().toString('ascii'); 

    var matches = line.match(/http:\/\/matchthis\.com/g); 
    for (var i = 0; i < matches.length; ++i) { 
     console.log(matches[i]); 
    } 
}); 

在这个例子中,我使用byline模块到流分割成线,这样你就不会通过让每.read()电话线的局部块错过比赛。

为了详细说明,你正在做的是将〜800MB的RAM作为缓冲区(V8的堆外部)分配,然后将其转换为ASCII字符串(从而将其转换为V8的堆),这将至少需要800MB,可能更多取决于V8的内部优化。我相信V8将字符串存储为UCS2或UTF16,这意味着每个字符将是2个字节(给定ASCII输入),所以您的字符串真的会大约为1600MB。

节点的最大分配堆空间为1.4GB,因此通过尝试创建如此大的字符串会导致V8引发异常。

Python没有这个问题,因为它没有最大的堆大小,并且会啃过所有的RAM。正如其他人所指出的那样,您还应该避免使用Python中的fh.read(),因为它会将所有文件数据作为字符串复制到RAM中,而不是使用迭代器逐行进行流式处理。

+0

这确实解决了错误,但是由于上述原因,确实比Python脚本花费了大约10-15秒的时间。 – bqui56

+0

什么是使用'readline'的Python时间? – hpaulj

+0

@hpaulj 2秒钟的用户和15秒的用户对'节点'和'byline'。 '节点'虽然没有经历800MB内存跳转。 – bqui56

1

鉴于这两个程序都试图将整个1400000文件读入内存,我建议Node和Python处理大字符串的方式有所不同。尝试逐行搜索,问题应该消失。

例如,在Python中,你可以这样做:

import re 
with open ('file.in', 'r') as file: 
    for line in file: 
     for match in re.findall(r'http://matchthis\.com', line): 
      print match 
相关问题