Le glob
premier crée toutes les extensions de nom de fichier possibles, donc il va d'abord générer la liste complète à partir du glob / modèle de style shell qui lui est donné. Ce n'est qu'alors qu'il itérera dessus, s'il est utilisé dans un contexte scalaire. C'est pourquoi il est si difficile (impossible?) D'échapper à l'itérateur sans l'épuiser; voir ce post .
Dans votre premier exemple, c'est 26 5 chaînes ( 11_881_376
), chacune de cinq caractères de long. Donc, une liste de ~ 12 millions de chaînes, avec un total (naïf) supérieur à 56 Mo ... plus les frais généraux pour un scalaire, qui je pense est au minimum de 12 octets ou autres. Donc, à l'ordre de 100 Mo, au moins, juste là dans une liste. †
Je ne suis pas au courant de limites formelles sur la longueur des choses en Perl (sauf dans regex) mais glob
fait tout cela en interne et il doit y avoir des limites non documentées - peut-être que certains tampons sont dépassés quelque part, en interne? C'est un peu excessif.
Quant à un moyen de contourner cela - générez cette liste de chaînes de 5 caractères de manière itérative, au lieu de laisser glob
rouler sa magie dans les coulisses. Ensuite, cela ne devrait absolument pas avoir de problème.
Cependant, je trouve le tout un peu grand pour le confort, même dans ce cas. Je recommanderais vraiment d'écrire un algorithme qui génère et fournit un élément de liste à la fois (un "itérateur"), et de travailler avec cela.
Il existe de bonnes bibliothèques qui peuvent le faire (et beaucoup plus), dont certaines sont Algorithm :: Loops recommandées dans un article précédent à ce sujet (et dans un commentaire), Algorithm :: Combinatorics (même commentaire), à Set::CrossProduct
partir d'une autre réponse ici ...
Notez également que, même s'il s'agit d'une utilisation intelligente de glob
, la bibliothèque est conçue pour fonctionner avec des fichiers. En dehors de son utilisation abusive en principe, je pense qu'il vérifiera chacun (les ~ 12 millions) de noms pour une entrée valide ! (Voir cette page .) C'est beaucoup de travail disque inutile. (Et si vous deviez utiliser des "globes" comme *
ou ?
sur certains systèmes, il retourne une liste avec uniquement des chaînes qui ont réellement des fichiers, donc vous obtiendrez tranquillement des résultats différents.)
† J'obtiens 56 octets pour une taille de scalaire de 5 caractères. Bien que cela soit pour une variable déclarée, qui peut prendre un peu plus qu'un scalaire anonyme, dans le programme de test avec des chaînes de longueur 4, la taille totale réelle est en effet d'un bon ordre de grandeur plus grande que celle calculée naïvement. Donc, la vraie chose pourrait bien être de l'ordre de 1 Go, en une seule opération.
Mise à jour Un programme de test simple qui génère cette liste de longues chaînes de 5 caractères (en utilisant la même glob
approche) a fonctionné pendant 15 minutes sur une machine de classe serveur et a pris 725 Mo de mémoire.
Il a produit le bon nombre de chaînes longues de 5 caractères, apparemment correctes, sur ce serveur.