perl正则表达式使用太多内存?

时间:2014-04-30 02:20:02

标签: regex perl memory-management out-of-memory

我有一个perl例程导致我经常在系统中出现“内存不足”问题。

脚本做了3件事

1> get the output of a  command to an array   (@arr = `$command`    --> array will hold about 13mb of data after the command)
2> Use a large regex to match the contents of individual array elements  -->

The regex is something like this
if($new_element =~ m|([A-Z0-9\-\._\$]+);\d+\s+([0-9]+)-([A-Z][A-Z][A-Z])-([0-9][0-9][0-9][0-9]([0-9]+)\:([0-9]+)\:([0-9]+)|io) 
<put to hash>
3> Put the array in a persistent hash map.
$hash_var{arr[0]} = "Some value"

修改 正则表达式处理的样本数据是

Z4:[newuser.newdir]TESTOPEN_ERROR.COM;4
                                                    8-APR-2014 11:14:12.58
Z4:[newuser.newdir]TEST_BOC.CFG;5
                                                    5-APR-2014 10:43:11.70
Z4:[newuser.newdir]TEST_BOC.COM;20
                                                    5-APR-2014 10:41:01.63
Z4:[newuser.newdir]TEST_NEWRT.COM;17
                                                    4-APR-2014 10:30:56.11

这些大约10000行

我开始怀疑数组和散列在一起可能会占用太多内存。 但是我开始认为这个正则表达式可能与内存不足有关。

perl正则表达式(带有'io'选项!)真的是造成内存不足的罪魁祸首吗?

2 个答案:

答案 0 :(得分:1)

这与正则表达式无关。

如果您在内存受限的环境中运行,则应一次处理一个数据记录,而不是一次性获取所有数据记录。我们假设您提取数据:

my @data = `some command`;
for my $line (@data) {
    ... # process the line
}

这非常浪费,因为您需要存储数据和处理输出(在您的情况下:哈希)。

相反,逐行处理输入。我们可以使用open函数代替反引号:

open my $cmd, '-|', 'some', 'command' or die "Can't run some command: $!";
while (my $line = <$cmd>) {
    ... # process the line
}

这里不需要一个数组,这可以为我们节省13MB的内存,我们现在就可以使用它了。

答案 1 :(得分:0)

你真的想解决什么问题? 用你的话......不是Perl。

类似于:&#34;脚本正在从openvms目录输出命令中分离输出,目标是报告按目录排序的文件数和最早日期&#34;

第一个问题是为什么要保留阵列。脚本会走路吗?它呢? 如果没有,只需在那里处理,然后在for循环中处理。

正则表达式似乎挑出了文件名和日期。以前就是这样。 它并不难,可以通过信任OpenVMS目录格式来简化。 像这样的某些东西读得更好imho:

if($ new_element = ~m |](。*); \ d + \ s +(\ d +) - (\ w +) - (\ d +)\ s +(\ d +):( d +):( \ d +) |)

  
    

:$ hash_var {arr [0]} =

  

嗯,这告诉我,数组中的整行用作关键值,所有50个以上的空格。因此,对于原始密钥字节,这些10,000行调整为1,000,000+字节。很多但不是疯了。新的我们知道线上的第一个字必须是唯一的,为什么不利用它:  $ hash_var {$ 1} = xxx if /(\ S +)/ l;

该程序可能还想利用前导字符串高度重复,并在&#34;]&#34;之前替换所有内容。随着不断增加的目录号码,保持在一个“看起来一边”的状态。数组和/或哈希。

我个人会从命令中删除/ NOHEAD,并使用正则表达式来获取目录,因为它们来自各自的行。

或使用SUBSTR或其他......当然,您需要在重新访问时构建类似的密钥。

在相关主题中,打印了调试输出。 也许包括数组中的行号以供您自己理解?

Perl encounters "out of memory" in openvms system

祝你好运! 海因