Я придумал свое собственное решение ... не то, чтобы я специально рекомендовал его или любые другие; в моем случае это скрипт модульного теста со ссылочными значениями в многомерной хеш-структуре. Я не буду вдаваться в технические подробности того, что эти вещи делают и почему, но конечный результат заключается в том, что небольшое исправление или изменение в коде может привести ко многим значениям, требующим обновления (после подтверждения изменения действительно). *
Поэтому я переместил хеш в секцию __DATA__
, используя Data::Dumper
. Код для записи этого в дескриптор файла выглядит так:
use Data::Dumper;
$Data::Dumper::Terse = 1; # to Eval whole thing as a hash
$Data::Dumper::Indent = 1; # Looks better, just a preference
$Data::Dumper::Sortkeys = 1; # To keep changes minimal in source control
print $fh Dumper(\%HASH);
В начале скрипта я загружаю хеш из DATA
после сохранения ссылок на позицию исходного дескриптора и mtime (mtime используется для гарантии того, что файл не был изменен во время выполнения скрипта).
use vars qw(%HASH $FILEPOS $MTIME);
{
$FILEPOS = tell(DATA);
$MTIME = (stat(DATA))[9];
local $/;
my $data = <DATA>;
%HASH = %{eval $data};
}
Наконец, чтобы обновить раздел __DATA__
, я открываю __FILE__
в $FILEPOS
, обрезаю его и пишу в него. Я упростил обработку ошибок для этого примера.
open(my $fh, '>>', __FILE__) or die $!;
seek($fh, $FILEPOS, 0) or die $!;
die "File changed" if ((stat($fh))[9] != $MTIME);
truncate($fh, $FILEPOS) or die $!;
# Assumes Dumper is already loaded and configured as in first code snippet
print $fh Dumper(\%HASH);
Обязательно сохраняйте резервные копии своих файлов, так как при их разработке одна ошибка может уничтожить весь ваш код!
Также обратите внимание, что то же самое будет работать с Storable
; хранение будет более эффективным и быстрым. Единственное предостережение в том, что он двоичный, что означает, что файл diff, скорее всего, не будет отображаться в управлении исходным кодом, и его не так легко редактировать, как вывод Dumper.