Perl的Glob有限制吗?

Ger*_*rry 6 perl

我正在运行以下期望返回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";
}
Run Code Online (Sandbox Code Playgroud)

但它仅返回4个字符:

anbc
anbd
anbe
anbf
anbg
...
Run Code Online (Sandbox Code Playgroud)

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

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

它正确返回:

aamid
aamie
aamif
aamig
aamih
...
Run Code Online (Sandbox Code Playgroud)

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

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

zdi*_*dim 8

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

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

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

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

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

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

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


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

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

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


bri*_*foy 6

一切都有一定的局限性。

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

use v5.10;

use Set::CrossProduct;

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

while( my $item = $set->get ) {
    say join '', @$item
    }
Run Code Online (Sandbox Code Playgroud)

  • Algorithm :: Loops的`NestedLoops`也可以使用:`use Algorithm :: Loops qw(NestedLoops); NestedLoops([([['a'..'z'])x 5],sub {say join``,@_}));`(OP先前的问题回答说,如果他们是内存不足...) (3认同)

归档时间:

查看次数:

128 次

最近记录:

6 年,1 月 前