2

DB_Fileモジュールを使用して参照ファイルの DBM インデックスを作成する Perl スクリプトがあります。次に、別の 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 ファイルにアクセスできない場合、次のいずれかを返します (DBM が A からのものである場合、マシン B で):

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

または、これ (マシン A で DBM が B からのもの):

Can't open names.dmp_IDs.dbm:

A にエラー メッセージが表示されない理由がわかりません。アクセスが制限されている Linux サーバーです。

4

2 に答える 2