2

我有一个 Perl 脚本,它使用DB_File模块创建参考文件的 DBM 索引。然后另一个 Perl 脚本使用该 DBM 文件。如果我在同一台机器上同时运行设置和使用脚本,它工作正常。

但是,如果我在机器 A 上制作 DBM 文件并将其复制到机器 B,则机器 B 上的使用脚本无法使用 DBM。

  • 两台机器都有 DB_File 版本 1.852。
  • DBM 文件是用 0666 权限创建的,果然,ls -ll 的权限字符串是“-rw-r--r--”。
  • 机器 A 有 Perl v5.26.2,B 有 v5.18.4。这种不匹配会是问题吗?B 是 Mac,我读到要获得更新版本的 Perl 并不简单。

参考文件(names.txt):

2   |   Bacteria    |   Bacteria <bacteria> |   scientific name |
4640    |   Musa    |       |   scientific name |
9606    |   Homo sapiens    |       |   scientific name |

制作 DBM 的安装脚本:

#!/usr/bin/perl

    use strict;
    use warnings;
    use DB_File;
    use Fcntl;

my $namesfile = "names.txt";

my $namesfileDBMids = $namesfile . '_IDs.dbm';     
my %namesfileDBMids = (); # Start the hash that will fill the DBM file.
tie (%namesfileDBMids, "DB_File", $namesfileDBMids, O_RDWR|O_CREAT, 0666, $DB_HASH) or die "Can't open $namesfileDBMids.\n$!\n";

open (my $names_filehandle, $namesfile) or die "Could not open $namesfile.\n$!\n"; # Open the input file and fill the hash.
while (1) { # Run this loop until "last" is called.
            my $line = <$names_filehandle>; # Read the next line from the names file.

            if (! defined $line) { last }; # If there is no next line, exit the loop. You've processed the whole file.

            my @line = split(/\|/, $line); # Otherwise, split the line by | characters.
            my $name = $line[1];
            $name =~ s/^\s+|\s+$//g; # Trim whitespace off the start and end.
            my $ID = $line[0];
            $ID =~ s/^\s+|\s+$//g;
            $namesfileDBMids{$ID} = $name; # Store in the hash.
}

close $names_filehandle;
untie %namesfileDBMids;
print "Finished indexing.\n";  

最后,这是使用 DBM 的使用脚本:

#!/usr/bin/perl

    use strict;
    use warnings;
    use DB_File;
    use Fcntl;

my $namesfileDBMids = "names.txt_IDs.dbm";

my $ID_to_look_up = 9606;

my %namesfileDBMids = (); # Set up a hash to hold the DBM file.
tie (%namesfileDBMids, "DB_File", $namesfileDBMids) or die "Can't open $namesfileDBMids: $!\n";

if (exists $namesfileDBMids{$ID_to_look_up}) {
    my $name = $namesfileDBMids{$ID_to_look_up};
    print "Found a name for ID $ID_to_look_up: $name\n";
} else {
    print "Couldn't find $ID_to_look_up in the names file.\n";
}

当使用脚本可以访问 DBM 文件时,它会返回以下行:

Found a name for ID 9606: Homo sapiens

当使用脚本无法访问 DBM 文件时,它要么返回这个(在机器 B 上,当 DBM 来自 A 时):

Can't open names.dmp_IDs.dbm: Inappropriate file type or format

或者这个(当 DBM 来自 B 时,在机器 A 上):

Can't open names.dmp_IDs.dbm:

我不确定为什么 A 上没有错误消息。这是我访问受限的 Linux 服务器。

4

2 回答 2

3

您的不同版本的 Perl 很可能是使用在二进制级别不兼容的不同版本的 DBM 库构建的。

我建议切换到基于文本的交换格式,如 YAML 或 JSON。

于 2019-08-22T11:00:00.690 回答
0

如果您在每台机器上创建 .dbm 文件,文件命令可能会显示版本不匹配。

问题可能来自 32 位/64 位、DB_File 类型或硬件字节序。

由于您提到版本 1.852,这意味着模块已更新。v5.18.4 附带 1.827,v5.26.2 附带 1.840。要尝试的一件事是回到核心 lib 版本并在 1.827 上制作 DB 文件,然后查看 1.840 是否可以读取它。反之亦然。

高温高压

于 2019-08-25T21:14:26.810 回答