如何在程序执行中保持标量值?

nik*_*ike 2 perl

代码示例var_inc1.pl:

#!/usr/bin/perl -w
my $x = 0;
$x++;
print "value : ".$x."\n";
Run Code Online (Sandbox Code Playgroud)

输出:

但我想要输出

...等等,标量值在每个程序执行时递增.

Cha*_*ens 8

一旦Perl程序结束,RAM中的所有内容都会消失.如果要在程序运行之间保留值,则需要某种形式的持久存储.您需要什么样的存储空间取决于您对环境的约束以及您需要什么形式的持久性(不同的用户应该看到相同的值并能够更改它,它应该存在多长时间等).

在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";
Run Code Online (Sandbox Code Playgroud)

通常,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";
Run Code Online (Sandbox Code Playgroud)

有时您不希望依赖外部资源,在这种情况下您可以编写自修改脚本:

#!/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
Run Code Online (Sandbox Code Playgroud)

请注意,这仅适用于要运行此脚本的所有用户都具有脚本写入权限的情况.如果允许多个用户运行脚本,则这是一个安全问题(因为一个用户可以修改脚本以包含将由其他用户运行的恶意代码).

当然,您也可以使用关系数据库:

#!/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;
Run Code Online (Sandbox Code Playgroud)


rei*_*ost 5

问题是要记住程序调用之间的值.

我想到了两种技术:

  1. 您可以让调用者记住该值并将其作为参数传递给Perl脚本.这就是在Web应用程序中维护状态的方式.如果您有不同的调用者调用相同的程序,则每个调用者都将维护自己的计数器.

  2. 您可以在永久存储中写入和读取值,例如文件.如果您有多个不同的调用者调用Perl程序,这将调用调用的总数,但是如果可以同时尝试多次调用,则必须注意打开存储以便以只有一次调用可以具有的方式进行写入它同时打开; 如果你想使用文件,请参阅例如perlopentut.