Perl中的取消引用哈希在Docker容器中不起作用

时间:2019-09-15 21:36:09

标签: perl docker

我有一个Perl脚本,可将文本文件的每一行加载到哈希中。

&load_map($word_file,"words");

sub load_map {
    my ($file_path,$assoc) = @_;
    open FILE, $file_path or die "Cannot open file $file_path";

    while ($line = <FILE>) {
    chomp $line;
        $$assoc{$line}=1;
    }
    close FILE;
}

稍后在脚本中,我查看哈希值以查看是否有一个词,然后再执行以下操作:

    if($words{$wordKey}) {
        do something...
    }

当我在本地环境中运行脚本时,此方法工作正常。当我在docker容器中运行此脚本时,$words{$wordKey}没有值或找不到,因此我需要运行的代码永远不会执行。

print $words{$wordKey}在docker容器中为空。在我的本地环境中为1。

奇怪的是,我知道哈希数据确实存在于docker容器中,因为如果我遍历整个哈希并逐个查看键1,我可以看到每个键并最终得到我所使用的键寻找,但这破坏了哈希的全部目的。我不必从头开始遍历整个哈希,直到找到我的密钥为止。

    while( my( $key, $value ) = each %words ){
        if($key == $wordKey) {
            Do something
        }
    }

有没有人遇到过这个问题,并且了解我可能会做或可能不会做的导致此问题的事情?这让我发疯。

================================================ ================

新代码和输出

情况1:

&preload_words($word_file);

sub preload_words {
    my %localhash;
    my ($file) = @_;
    open my $fh, '<', $file or die "Can't open $file: $!";

    my $avalue;
    while (my $line = <$fh>) {
        chomp $line;
        $localhash{$line}=1;

        print "word: $line, local value: $localhash{$line} \n";
        $avalue = $line;
    }
    close $fh;

    print "a word: $avalue, a value: $localhash{$avalue} \n";

    my $bvalue = $localhash{'written'};
    print "b word: written, b value: $bvalue \n";
}


outputs:

...
word: worn, local value: 1
word: win, local value: 1
word: won, local value: 1
word: write, local value: 1
word: wrote, local value: 1
word: written, local value: 1 <-- last print from loop
a word: written, a value: 1 <-- avalue last dynamically set from loop
b word: written, b value: 1 <-- hardcoded last word of loop print

情况2:

&preload_words($word_file);

sub preload_words {
    my %localhash;
    my ($file) = @_;
    open my $fh, '<', $file or die "Can't open $file: $!";

    my $avalue;
    while (my $line = <$fh>) {
        chomp $line;
        $localhash{$line}=1;

        print "word: $line, local value: $localhash{$line} \n";
        $avalue = $line;
    }
    close $fh;

    print "a word: $avalue, a value: $localhash{$avalue} \n";

    my $bvalue = $localhash{'wrote'};
    print "b word: wrote, b value: $bvalue \n";
}

...
word: worn, local value: 1
word: win, local value: 1
word: won, local value: 1
word: write, local value: 1
word: wrote, local value: 1 <-- prints value in loop but nothing outside of loop scope.
word: written, local value: 1 <-- last print from loop
a word: written, a value: 1 <-- avalue last dynamically set from loop
b word: wrote, b value:  <-- hardcoded 2nd to last word of loop print returns no value

即使在同一功能内,这似乎也是容器中的某种范围界定问题。一旦退出while循环,我只能直接取消引用最后一个索引。有想法吗?

2 个答案:

答案 0 :(得分:6)

我不知道“ docker容器”的作用,但是您使用的是符号引用(从字符串中获取变量名),因此您永远都不要如此轻轻松松...如果有的话;请参见in perlfaq7this article seriesthis post(对于初学者)。

此外,这里甚至没有暗示它的原因-而不是使用字符串文字("words")来创建哈希名称,而只是传递哈希引用。或在子代码中构建一个哈希值,然后返回它或它的引用

sub load_map {
    my ($file) = @_;
    open my $fh, '<', $file or die "Can't open $file: $!";

    my %assoc;    
    while (my $line = <$fh>) {
        chomp $line;
        $assoc{$line} = 1;
    }
    return \%assoc;
}

并将其作为例如在呼叫方中获取

my %words = %{ load_map('filename') };

如果在此之前调用者中存在哈希的原因,则将其引用传递给子对象

my %words;
...
load_map('filename', \%words);

,然后在子项中使用该哈希值

sub load_map { 
    my ($file, $assoc) = @_;
    ...
    while (my $line = <$fh>) { 
        chomp $line;
        $assoc->{$line} = 1
    }
    return 1;
}

请注意,将文件打开到$fh后,您可以简单地通过以下方式填充哈希值:

my %assoc = map { chomp; $_ => 1 } <$fh>;

由于列表上下文中的readline(又名<>)(在此处由map强制执行,因此会返回文件中的所有行。

但是,上面显式的逐行代码使您可以随时检查等。

我不理解其余的问题(似乎是解释?),但是我在这里解决的问题显然已经消失并正在寻找麻烦(“ docker ”问题可能是由于那?);需要纠正。

答案 1 :(得分:2)

我最终按照zdim的建议使用Data::Dump打印哈希键,结果表明,从文件构建哈希键时,它以someword\r的形式存储。

Chomp仅从末尾删除了\n,而将\r作为密钥的一部分,这最终导致对密钥的所有取消引用或比较都无法成功。

我将保留大家都建议的代码更改建议,但是想告知任何对此错误的根本原因感兴趣的人。

再次感谢您的所有帮助和建议!