【问题标题】:How to store data from hash in file and use it for another hash如何将哈希中的数据存储在文件中并将其用于另一个哈希
【发布时间】:2020-08-17 14:54:36
【问题描述】:

我是 Perl 世界的新手,我需要有关从文件中的散列中保存数据以及之后在另一个散列中使用它的帮助。

这是我的代码的一个简短示例:

#!/usr/local/bin/perl
use FileHandle;
use File::Copy;
use Data::Dumper qw(Dumper);
use Storable;
use warnings;
use strict;

my $user_data;

$user_data->{test_user}->{1256489043}->{STATUS}     =  "RUN";
$user_data->{test_user}->{1256489043}->{MEM}        =  "51591";
$user_data->{test_user}->{1256489043}->{RUN_TIME}   =  "41410";
$user_data->{test_user}->{1256489043}->{PROJ_NAME}  =  "unkown";
$user_data->{test_user}->{1256489043}->{GROUP}      =  "default";
$user_data->{test_user}->{1256489043}->{DATE}       =  "Aug 17 05:23";

$user_data->{test_user_2}->{528562752}->{STATUS}     =  "RUN";
$user_data->{test_user_2}->{528562752}->{MEM}        =  "591";
$user_data->{test_user_2}->{528562752}->{RUN_TIME}   =  "46410";
$user_data->{test_user_2}->{528562752}->{PROJ_NAME}  =  "unkown";
$user_data->{test_user_2}->{528562752}->{GROUP}      =  "default";
$user_data->{test_user_2}->{528562752}->{DATE}       =  "Aug 17 05:23";

store (\$user_data, 'temp_jobs.txt') or die "can't store data to $!";
my $data = retrieve('temp_jobs.txt');

print "Hash 1\n";
print Dumper \$user_data;

print "Hash2\n";
print Dumper \$data;

my @new_array_id;
foreach my $user (keys %{$user_data}) {
   foreach my $job_id (keys %{$user_data->{$user}}) {
      push (@new_array_id, $job_id)
   }
}

my @old_array_id;
foreach my $user (keys %{$data}) {
   foreach my $job_id (keys %{$data->{$user}}) {
      push (@old_array_id, $job_id)
   }
}

这些是 Dumper 打印的输出:

$VAR1 = \{
            'test_user_2' => {
                               '528562752' => {
                                                'GROUP' => 'default',
                                                'PROJ_NAME' => 'unkown',
                                                'DATE' => 'Aug 17 05:23',
                                                'STATUS' => 'RUN',
                                                'RUN_TIME' => '46410',
                                                'MEM' => '591'
                                              }
                             },
            'test_user' => {
                             '1256489043' => {
                                               'GROUP' => 'default',
                                               'PROJ_NAME' => 'unkown',
                                               'DATE' => 'Aug 17 05:23',
                                               'STATUS' => 'RUN',
                                               'RUN_TIME' => '41410',
                                               'MEM' => '51591'
                                             }
                           }
          };

$VAR1 = \\{
              'test_user' => {
                               '1256489043' => {
                                                 'GROUP' => 'default',
                                                 'PROJ_NAME' => 'unkown',
                                                 'DATE' => 'Aug 17 05:23',
                                                 'STATUS' => 'RUN',
                                                 'RUN_TIME' => '41410',
                                                 'MEM' => '51591'
                                               }
                             },
              'test_user_2' => {
                                 '528562752' => {
                                                  'GROUP' => 'default',
                                                  'PROJ_NAME' => 'unkown',
                                                  'DATE' => 'Aug 17 05:23',
                                                  'STATUS' => 'RUN',
                                                  'RUN_TIME' => '46410',
                                                  'MEM' => '591'
                                                }
                               }
            };

在第二个 foreach 循环中观察到错误:

foreach my $user (keys %{$data}) {
   foreach my $job_id (keys %{$data->{$user}}) {
      push (@old_array_id, $job_id)
   }
}

输出:report.pl 中不是 HASH 引用`

实际上,我不确定检索到的数据的类型。您能帮忙将数据保存在新的哈希中吗?

最好的问候, SK

【问题讨论】:

  • 提示:store (\$user_data, ... 应该是 store ($user_data, ...。想将标量传递给Dumper,因此使用\@a\%h 用于数组和散列,但标量已经是标量,因此使用\$s 只会让事情变得复杂
  • 糟糕,我没有意识到这是问题的根本原因

标签: perl hash storable


【解决方案1】:

您的$user_data 变量包含一个哈希引用。哈希引用是一个标量值。我认为您对 documentation for Storable 的概要感到困惑,其中包含如下示例:

store \%table, 'file';

在上面的例子中,%table 是一个哈希值。因此,您需要引用它才能将其传递给store()。因为你在$user_data 中拥有的是一个哈希引用,而不是一个哈希,你不需要在将它传递给store() 之前获取它的引用。事实上,通过引用它,您已经添加了额外的间接级别,这会破坏您的代码。

你说:

其实我并不确定检索到的数据的类型。

它是对哈希引用的引用。但是您的代码只需要一个哈希引用。

最简单的解决方法是替换:

store (\$user_data, 'temp_jobs.txt') ... ;

store ($user_data, 'temp_jobs.txt') ... ;

删除单个字符后,您的两个数据结构相同,并且您的代码按预期工作。

【讨论】:

    【解决方案2】:

    我喜欢将 Yaml::XS 用于基本数据结构,它们以后更容易查看。我已经包含了YAML::XSStorable 的示例

    希望这会有所帮助

    #!/usr/bin/env perl
    
    use strict;
    use warnings; 
    use Storable;
    use YAML::XS;
    use Data::Dumper;
    
    my $struct = {
    'test_user_2' => {
       '528562752' => {
                        'GROUP' => 'default',
                        'PROJ_NAME' => 'unkown',
                        'DATE' => 'Aug 17 05:23',
                        'STATUS' => 'RUN',
                        'RUN_TIME' => '46410',
                        'MEM' => '591'
                      }
     },
    'test_user' => {
     '1256489043' => {
                       'GROUP' => 'default',
                       'PROJ_NAME' => 'unkown',
                       'DATE' => 'Aug 17 05:23',
                       'STATUS' => 'RUN',
                       'RUN_TIME' => '41410',
                       'MEM' => '51591'
                     }
    }
    
    };
    
    
    #print Dumper($struct);
    
    #print Dump($struct);
    
    YAML::XS::DumpFile("store.yaml", $struct);
    my $read_yml = YAML::XS::LoadFile("store.yaml");
    print "yaml out\n";
    print Dumper($read_yml);
    
    store $struct, 'store.perl_str';
    my $hashref = retrieve('store.perl_str');
    print "store out\n";
    print Dumper($hashref);
    
    print "looping  data\n";
    for my $user_key ( sort keys %{ $hashref } )
    {
        my $user = $hashref->{$user_key};
        for my $id_key ( sort keys %{ $user } )
        {
            print "$user_key - $id_key\n";
            print "   " . $user->{$id_key}{"DATE"} . "\n";
            print "   " . $user->{$id_key}{"STATUS"} . "\n";
        }
    }
    

    【讨论】:

    • 您修复了 OP 的问题(store $struct 而不是 store \$struct),但您没有指出实际的修复是什么。如果 OP 继续尝试序列化 \$struct 并反序列化为 $struct,则切换到另一种序列化格式不会有任何区别。
    • @dave 你是绝对正确的。我错过了。但是,我确实觉得,如果可以简化代码,那么问题就会消失。将数据存储在 yaml(或 json 或其他东西)中确实使直接查看文件变得容易得多,这无疑在某些时候会想要这样做。
    • 我认为您的示例令人困惑,因为它进行了两次的序列化和反序列化。 $read_yml 实际上已经反序列化 $hashref 并且从未使用过。 YAML::XS::LoadFile() 已经根据此解释为您提供了您正在寻找的$hashrefperl.com/article/29/2013/9/17/How-to-Load-YAML-Config-Files。您应该坚持仅使用 1 种序列化方法以获得更清晰的代码。
    【解决方案3】:

    作为一个选项,您可以将哈希保存到 JSON 文件中。下面的代码演示了如何实现预期的结果。

    use strict;
    use warnings;
    use feature 'say';
    
    use JSON;
    use Data::Dumper;
    
    my $fname = 'datafile.json';
    my $user_data;
    
    $user_data->{test_user}{1256489043}{STATUS}      =  "RUN";
    $user_data->{test_user}{1256489043}{MEM}         =  "51591";
    $user_data->{test_user}{1256489043}{RUN_TIME}    =  "41410";
    $user_data->{test_user}{1256489043}{PROJ_NAME}   =  "unkown";
    $user_data->{test_user}{1256489043}{GROUP}       =  "default";
    $user_data->{test_user}{1256489043}{DATE}        =  "Aug 17 05:23";
    
    $user_data->{test_user_2}{528562752}{STATUS}     =  "RUN";
    $user_data->{test_user_2}{528562752}{MEM}        =  "591";
    $user_data->{test_user_2}{528562752}{RUN_TIME}   =  "46410";
    $user_data->{test_user_2}{528562752}{PROJ_NAME}  =  "unkown";
    $user_data->{test_user_2}{528562752}{GROUP}      =  "default";
    $user_data->{test_user_2}{528562752}{DATE}       =  "Aug 17 05:23";
    
    my $json = to_json($user_data);
    
    write_json($fname,$json);
    
    my $data = read_json($fname);
    
    say '--- Read from file -----------------';
    say Dumper($data);
    say '-' x 45;
    say Dumper( jobs_array($user_data) );
    say '-' x 45;
    say Dumper( jobs_array($data) );
    
    
    sub jobs_array {
        my $data = shift;
        my @array;
        
        for my $user ( keys %{$data} ) {
            for my $job_id ( keys %{$data->{$user}} ) {
                push @array, $job_id;
            }
        }
        
        return \@array;
    }
    
    
    sub write_json {
        my $fname = shift;
        my $data  = shift;
        
        open my $fh, '>', $fname
            or die "Couldn't open $fname";
            
        say $fh $data;
        
        close $fh;
    }
    
    sub read_json {
        my $fname = shift;
        
        open my $fh, '<', $fname
            or "Couldn't open $fname";
            
        my $data = do{ local $/; <$fh> };
        
        close $fh;
        
        my $href = from_json($data);
        
        return $href;
    }
    

    输出

    --- Read from file -----------------
    $VAR1 = {
              'test_user' => {
                               '1256489043' => {
                                                 'RUN_TIME' => '41410',
                                                 'MEM' => '51591',
                                                 'PROJ_NAME' => 'unkown',
                                                 'STATUS' => 'RUN',
                                                 'GROUP' => 'default',
                                                 'DATE' => 'Aug 17 05:23'
                                               }
                             },
              'test_user_2' => {
                                 '528562752' => {
                                                  'GROUP' => 'default',
                                                  'STATUS' => 'RUN',
                                                  'MEM' => '591',
                                                  'PROJ_NAME' => 'unkown',
                                                  'DATE' => 'Aug 17 05:23',
                                                  'RUN_TIME' => '46410'
                                                }
                               }
            };
    
    ---------------------------------------------
    $VAR1 = [
              '1256489043',
              '528562752'
            ];
    
    ---------------------------------------------
    $VAR1 = [
              '1256489043',
              '528562752'
            ];
    
    

    【讨论】:

    • 我同意 JSON(或 YAML)在这里会是更好的序列化格式。但改变格式并不会改变根本问题。如果 OP 序列化一个对哈希引用的引用并反序列化它,期望得到一个哈希引用,那么无论他们选择哪种格式,他们都会遇到完全相同的问题。
    猜你喜欢
    • 2020-02-20
    • 2012-02-01
    • 2014-03-30
    • 1970-01-01
    • 2021-02-03
    • 2012-07-15
    • 2012-11-19
    • 2015-12-03
    • 1970-01-01
    相关资源
    最近更新 更多