当前位置:  开发笔记 > 编程语言 > 正文

Perl的Glob有限制吗?

如何解决《Perl的Glob有限制吗?》经验,为你挑选了2个好方法。

我正在运行以下期望返回5个字符的字符串:

while (glob '{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}'x5) {
  print "$_\n";
}

但它仅返回4个字符:

anbc
anbd
anbe
anbf
anbg
...

但是,当我减少列表中的字符数时:

while (glob '{a,b,c,d,e,f,g,h,i,j,k,l,m}'x5) {
  print "$_\n";
}

它正确返回:

aamid
aamie
aamif
aamig
aamih
...

有人可以告诉我我在这里缺少什么吗?是否有某种限制?还是有办法解决?

如果有什么不同,则在perl 5.26和中返回相同的结果perl 5.28



1> zdim..:

glob一个创建所有可能的文件扩展名,因此它将首先从给定的shell样式的glob / pattern 生成完整列表。如果在标量上下文中使用,则只有这样才能对其进行迭代。这就是为什么要逃避迭代器而不用尽它是如此困难(不可能?)的原因。看到这篇文章。

在您的第一个示例中,有26个5个字符串(11_881_376),每个字符串5个字符。因此,大约有1200万个字符串的列表,(原始)总数超过56Mb ...加上标量的开销,我认为标量的开销至少为12个字节左右。因此,至少在一个列表中至少有一个100Mb的数量级。

我不知道对Perl中的事物长度有任何正式的限制(正则表达式中除外),但是glob内部是否全部都存在,并且必须有未记录的限制-也许某些缓冲区在内部某个地方溢出了?有点过分了。

关于此问题的解决方法-迭代生成该5个字符的字符串列表,而不是让其glob幕后推手。那么它绝对不应该有问题。

但是,即使在那种情况下,我发现整个过程还是有点舒适。我真的建议编写一种算法,一次生成并提供一个列表元素(“迭代器”),然后使用该算法。

有很好的库可以做到这一点(还有更多),其中一些是以前的帖子(和评论)中推荐的Algorithm :: Loops,Algorithm :: Combinatorics(同样的评论),Set::CrossProduct来自另一个答案。这里 ...

还要注意,虽然这是的巧妙用法glob,但该库是用于处理文件的。除了原则上滥用它外,我认为它将检查(〜1200万个)名称中的每个名称是否有效!(请参阅本页。)这是很多不需要的磁盘工作。(并且,如果您要像在某些系统上使用“ globs”那样,*或者?在某些系统上使用它,它会返回仅包含实际上具有文件的字符串的列表,因此您会悄悄地获得不同的结果。)


 我得到56个字节的5个字符的标量。尽管这是一个声明的变量,它可能比匿名标量花费更多,但是在具有长度为4的字符串的测试程序中,实际总大小确实比幼稚计算的大小大一个数量级。因此,一次操作中,真实的东西很可能约为1Gb。

更新   一个简单的测试程序(使用相同的glob方法)生成5字符长字符串的列表,在服务器级计算机上运行了15分钟,并占用了725 Mb的内存。

它确实在此服务器上产生了正确数量的实际5字符长字符串,看似正确。



2> brian d foy..:

一切都有一定的局限性。

这是一个纯Perl模块,可以为您反复进行。它不会立即生成整个列表,您会立即开始获得结果:

use v5.10;

use Set::CrossProduct;

my $set = Set::CrossProduct->new( [ ([ 'a'..'z' ]) x 5 ] );

while( my $item = $set->get ) {
    say join '', @$item
    }


Algorithm :: Loops的`NestedLoops`也可以使用:`use Algorithm :: Loops qw(NestedLoops); NestedLoops([([['a'..'z'])x 5],sub {say join``,@_}));`(OP先前的问题回答说,如果他们是内存不足...)
推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有