Как только Perl-программа заканчивается, все в оперативной памяти исчезает. Если вы хотите, чтобы значение сохранялось между запусками программы, вам нужна некоторая форма постоянного хранения. Какой тип хранилища вам нужен, зависит от того, какие ограничения вашей среды вам нужны и какая форма сохранения вам нужна (если разные пользователи увидят одно и то же значение и смогут его изменить, как долго он должен жить и т. Д.).
Самый простой (но не самый лучший) способ получить постоянство в Perl 5 - использовать функцию dbmopen
для создания / открытия файла DBM, связанного с хешем:
#!/usr/bin/perl
use strict;
use warnings;
dbmopen my %storage, "/tmp/foo.db", 0666 #anyone can write to it
or die "could not open /tmp/foo.db: $!";
my $x = ++$storage{x};
print "$x\n";
В общем случае dbmopen
было заменено на tie
, что является более общим способом связывания кода с переменными. Более современный подход к приведенному выше коду:
#!/usr/bin/perl
use strict;
use warnings;
use DB_File;
tie my %storage, "DB_File", "/tmp/bar.db"
or die "could not open /tmp/bar.db: $!";
my $x = ++$storage{x};
print "$x\n";
Иногда вы не хотите зависеть от внешнего ресурса, в таких случаях вы можете просто написать самоизменяющийся скрипт:
#!/usr/bin/perl
use strict;
use warnings;
my $pos = tell DATA;
my $x = <DATA>;
$x++;
open DATA, "+<", $0
or die "could not open $0 in read/write mode: $!";
seek DATA, $pos, 0
or die "could not seek to $pos in $0";
print DATA "$x\n"; #save the current value
print "$x\n";
__DATA__
1
Обратите внимание, это работает только в том случае, если все пользователи, которые будут запускать этот сценарий, имеют разрешение на запись в сценарий. Это проблема безопасности, если сценарию разрешено запускать несколько пользователей (поскольку один пользователь может изменить сценарий, добавив в него вредоносный код, который будет запускаться другими пользователями).
Конечно, вы также можете использовать реляционную базу данных:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $db = "/tmp/baz.db";
my $dbh = DBI->connect(
"dbi:SQLite:dbname=$db",
"", # SQLite doesn't do auth, so make sure the file
"", # permissions are what you need them to be
{
AutoCommit => 1,
PrintError => 0,
RaiseError => 1,
ChopBlanks => 1,
FetchHashKeyName => "NAME_lc",
}
) or die "could not connect to $db: ", DBI->errstr;
my $count = $dbh->selectcol_arrayref("
SELECT count(*)
FROM sqlite_master
WHERE type='table'
AND name='counter';
")->[0];
unless ($count) {
$dbh->do("
CREATE TABLE counter (
name char(50),
value int
);
");
$dbh->do("INSERT INTO counter (name, value) VALUES ('x', 0)");
}
my $x = $dbh->selectcol_arrayref("
SELECT value
FROM counter
WHERE name = 'x'
")->[0];
$x++;
print "$x\n";
$dbh->do("UPDATE counter SET value = ? WHERE name = ?", {}, $x, "x");
$dbh->disconnect;