glob
Первым создает все возможные расширения имен файлов, поэтому он будет первым генерировать полный список из оболочки стиль Глоб / шаблона это дается. Только тогда он будет перебирать его, если он используется в скалярном контексте. Вот почему так трудно (невозможно?) Избежать итератора, не исчерпав его; см этого поста .
В вашем первом примере это 26 5 строк ( 11_881_376
), каждая длиной пять символов. Итак, список из ~ 12 миллионов строк, с общим количеством (наивных) свыше 56 МБ ... плюс накладные расходы для скаляра, который, я думаю, составляет минимум 12 байтов или около того. Таким образом, порядка 100 МБ, по крайней мере, прямо в одном списке. †
Я не знаю каких-либо формальных ограничений на длину вещей в Perl (кроме как в регулярных выражениях), но glob
делает ли это все внутренне и должны быть недокументированные ограничения - возможно, некоторые буферы где-то переполнены, внутренне? Это немного чрезмерно.
Что касается способа обойти это - генерировать этот список из 5-ти символьных строк итеративно, вместо того, чтобы позволять glob
сворачивать свою магию за кулисы. Тогда это абсолютно не должно иметь проблемы.
Тем не менее, я нахожу все это немного большим для комфорта, даже в этом случае. Я действительно рекомендую написать алгоритм, который генерирует и предоставляет один элемент списка за раз («итератор»), и работать с этим.
Есть хорошие библиотеки, которые могут сделать это (и многое другое), некоторые из которых Algorithm :: Loops, рекомендованные в предыдущем посте по этому вопросу (и в комментарии), Algorithm :: Combinatorics (тот же комментарий), Set::CrossProduct
из другого ответа Вот ...
Также обратите внимание, что, хотя это разумное использование glob
, библиотека предназначена для работы с файлами. Помимо неправильного использования в принципе, я думаю, что он проверит каждое из (~ 12 миллионов) имен на правильность записи ! (См. Эту страницу .) Это много ненужной работы с диском. (И если бы вы использовали «globs», как *
или ?
в некоторых системах, он возвращает список только с теми строками, которые действительно имеют файлы, так что вы спокойно получили бы другие результаты.)
† Я получаю 56 байтов за размер скаляра из 5 символов. В то время как это для объявленной переменной, которая может занять немного больше, чем анонимный скаляр, в тестовой программе со строками длины 4 фактический общий размер действительно на порядок больше, чем вычисляемый наивно. Так что реальная вещь вполне может быть порядка 1 Гб за одну операцию.
Обновление Простая тестовая программа, которая генерирует этот список из 5-символьных длинных строк (используя тот же glob
подход), выполнялась в течение 15 минут на компьютере серверного класса и занимала 725 МБ памяти.
Это произвело правильное количество фактических 5-символьных длинных строк, казалось бы, правильных, на этом сервере.