【问题标题】:Error using keys on a hash在哈希上使用键时出错
【发布时间】:2014-09-03 17:03:15
【问题描述】:

我有以下代码:

my $xmlrpc = XML::RPC->new('http://api.opensubtitles.org/xml-rpc');
my $result = $xmlrpc->call('SearchSubtitles', $token, @args);    

&lp ("Number of subtitle files found:".keys $result->{data});
my $count=0;
mkdir "./Subs";
foreach my $key ( keys $result->{data} )
{

编译失败并出现错误:

Type of argument to keys on reference must be unblessed hashref or arrayref at /root/subtitlegetter/getsubs.pl line 210.

在包含keys 语句的两行中。

$result 看起来像这样:

$result  = {
          'seconds' => '0.014',
          'status' => '200 OK',
          'data' => [
                      {
                        'SubFeatured' => '0',
                        'SubHearingImpaired' => '0',
                        'SubAuthorComment' => undef,
                        'SubDownloadLink' => 'http://dl.opensubtitles.org/en/download/filead/src-api/vrf-cc714a2b91/1951829762.gz',
                        'MovieNameEng' => undef,
                        'SubDownloadsCnt' => '2225',
                        'MovieName' => '"24" Day 4: 7:00 a.m.-8:00 a.m.',
                        'LanguageName' => 'English',
                        'MovieFPS' => '25.000',
                        'SeriesIMDBParent' => '285331',
                        'MovieHash' => '9dfc670867516a39',
                        'SeriesEpisode' => '1',
                        'UserNickName' => 'dvkempen',
                        'MovieYear' => '2005',
                        'SubSize' => '41095',
                        'MovieKind' => 'episode',
                        'IDSubMovieFile' => '125384',
                        'ZipDownloadLink' => 'http://dl.opensubtitles.org/en/download/subad/src-api/vrf-b48cd22d58/3253187',
                        'SubBad' => '0',
                        'ISO639' => 'en',
                        'IDSubtitle' => '3253187',
                        'MovieReleaseName' => '24.S04E01.WS.DVDRip.XviD-MEDiEVAL',
                        'MatchedBy' => 'moviehash',
                        'MovieTimeMS' => '2474000',
                        'UserID' => '1019339',
                        'SubFormat' => 'srt',
                        'MovieByteSize' => '366661632',
                        'SubRating' => '0.0',
                        'SubComments' => '0',
                        'SubActualCD' => '1',
                        'SubHash' => 'ab8ad6d19af1579361929b3f71d61b60',
                        'UserRank' => 'silver member',
                        'IDSubtitleFile' => '1951829762',
                        'SubSumCD' => '1',
                        'SubFileName' => '24.S04E01.WS.DVDRip.XviD-MEDiEVAL.srt',
                        'SubAddDate' => '2008-02-24 20:44:01',
                        'IDMovieImdb' => '502251',
                        'SubtitlesLink' => 'http://www.opensubtitles.org/en/subtitles/3253187/24-day-4-7-00-a-m-8-00-a-m-en',
                        'IDMovie' => '73012',
                        'SeriesSeason' => '4',
                        'SubHD' => '0',
                        'SubLanguageID' => 'eng',
                        'MovieImdbRating' => '8.5'
                      },
                      {
                        'SubFeatured' => '0',
                        'SubHearingImpaired' => '0',
                        'SubAuthorComment' => undef,
                        'SubDownloadLink' => 'http://dl.opensubtitles.org/en/download/filead/src-api/vrf-d165613c14/1951854096.gz',
                        'MovieNameEng' => undef,
                        'SubDownloadsCnt' => '4521',
                        'MovieName' => '"24" Day 4: 7:00 a.m.-8:00 a.m.',
                        'LanguageName' => 'English',
                        'MovieFPS' => '25.000',
                        'SeriesIMDBParent' => '285331',
                        'MovieHash' => '9dfc670867516a39',
                        'SeriesEpisode' => '1',
                        'UserNickName' => 'mephistogrigo',
                        'MovieYear' => '2005',
                        'SubSize' => '40794',
                        'MovieKind' => 'episode',
                        'IDSubMovieFile' => '144086',
                        'ZipDownloadLink' => 'http://dl.opensubtitles.org/en/download/subad/src-api/vrf-18f9de1a19/4380524',
                        'SubBad' => '0',
                        'ISO639' => 'en',
                        'IDSubtitle' => '4380524',
                        'MovieReleaseName' => '24.Season.4.DVDRip.XviD-MEDiEVAL',
                        'MatchedBy' => 'moviehash',
                        'MovieTimeMS' => '2474000',
                        'UserID' => '446711',
                        'SubFormat' => 'srt',
                        'MovieByteSize' => '366661632',
                        'SubRating' => '0.0',
                        'SubComments' => '0',
                        'SubActualCD' => '1',
                        'SubHash' => '4d9d67b580efe4b6378d3cb34b4d2a75',
                        'UserRank' => 'gold member',
                        'IDSubtitleFile' => '1951854096',
                        'SubSumCD' => '1',
                        'SubFileName' => '24.4x01.Day.4.07am-08am.DVDRip.XviD.iNTERNAL-MEDiEVAL.EN.srt',
                        'SubAddDate' => '2008-04-13 14:23:34',
                        'IDMovieImdb' => '502251',
                        'SubtitlesLink' => 'http://www.opensubtitles.org/en/subtitles/4380524/24-day-4-7-00-a-m-8-00-a-m-en',
                        'IDMovie' => '73012',
                        'SeriesSeason' => '4',
                        'SubHD' => '0',
                        'SubLanguageID' => 'eng',
                        'MovieImdbRating' => '8.5'
                      },
                      {
                        'SubFeatured' => '0',
                        'SubHearingImpaired' => '0',
                        'SubAuthorComment' => undef,
                        'SubDownloadLink' => 'http://dl.opensubtitles.org/en/download/filead/src-api/vrf-d383210797/138228.gz',
                        'MovieNameEng' => undef,
                        'SubDownloadsCnt' => '582',
                        'MovieName' => '"24" Day 4: 7:00 a.m.-8:00 a.m.',
                        'LanguageName' => 'English',
                        'MovieFPS' => '25.000',
                        'SeriesIMDBParent' => '285331',
                        'MovieHash' => '9dfc670867516a39',
                        'SeriesEpisode' => '1',
                        'UserNickName' => 'wr975 (a)',
                        'MovieYear' => '2005',
                        'SubSize' => '41175',
                        'MovieKind' => 'episode',
                        'IDSubMovieFile' => '2004768',
                        'ZipDownloadLink' => 'http://dl.opensubtitles.org/en/download/subad/src-api/vrf-b7f71cab8b/4292367',
                        'SubBad' => '0',
                        'ISO639' => 'en',
                        'IDSubtitle' => '4292367',
                        'MovieReleaseName' => '24 - Season 4 - E01-08',
                        'MatchedBy' => 'moviehash',
                        'MovieTimeMS' => '0',
                        'UserID' => '48281',
                        'SubFormat' => 'srt',
                        'MovieByteSize' => '366661632',
                        'SubRating' => '0.0',
                        'SubComments' => '0',
                        'SubActualCD' => '1',
                        'SubHash' => 'b6c8e5422afbb6d748040c5d401445e3',
                        'UserRank' => 'bronze member',
                        'IDSubtitleFile' => '138228',
                        'SubSumCD' => '1',
                        'SubFileName' => '24.401-med.srt',
                        'SubAddDate' => '2005-08-23 00:00:00',
                        'IDMovieImdb' => '502251',
                        'SubtitlesLink' => 'http://www.opensubtitles.org/en/subtitles/4292367/24-day-4-7-00-a-m-8-00-a-m-en',
                        'IDMovie' => '73012',
                        'SeriesSeason' => '4',
                        'SubHD' => '0',
                        'SubLanguageID' => 'eng',
                        'MovieImdbRating' => '8.5'
                      },
                      {
                        'SubFeatured' => '0',
                        'SubHearingImpaired' => '0',
                        'SubAuthorComment' => undef,
                        'SubDownloadLink' => 'http://dl.opensubtitles.org/en/download/filead/src-api/vrf-d596b9fa4f/1952794930.gz',
                        'MovieNameEng' => undef,
                        'SubDownloadsCnt' => '772',
                        'MovieName' => '"24" Day 4: 7:00 a.m.-8:00 a.m.',
                        'LanguageName' => 'English',
                        'MovieFPS' => '25.000',
                        'SeriesIMDBParent' => '285331',
                        'MovieHash' => '9dfc670867516a39',
                        'SeriesEpisode' => '1',
                        'UserNickName' => undef,
                        'MovieYear' => '2005',
                        'SubSize' => '41307',
                        'MovieKind' => 'episode',
                        'IDSubMovieFile' => '2587404',
                        'ZipDownloadLink' => 'http://dl.opensubtitles.org/en/download/subad/src-api/vrf-627cac3bd1/4119493',
                        'SubBad' => '0',
                        'ISO639' => 'en',
                        'IDSubtitle' => '4119493',
                        'MovieReleaseName' => 'S04E01 iNTERNAL WS DVDRip XviD MEDiEVAL',
                        'MatchedBy' => 'moviehash',
                        'MovieTimeMS' => '0',
                        'UserID' => '0',
                        'SubFormat' => 'srt',
                        'MovieByteSize' => '366661632',
                        'SubRating' => '0.0',
                        'SubComments' => '0',
                        'SubActualCD' => '1',
                        'SubHash' => '295dfd2ab8ded0c6d14ed6555796f9d0',
                        'UserRank' => undef,
                        'IDSubtitleFile' => '1952794930',
                        'SubSumCD' => '1',
                        'SubFileName' => '24.S04E01.iNTERNAL.WS.DVDRip.XviD-MEDiEVAL_(ENGLISH)_DJJ.HOME.SAPO.PT.srt',
                        'SubAddDate' => '2011-03-01 22:37:54',
                        'IDMovieImdb' => '502251',
                        'SubtitlesLink' => 'http://www.opensubtitles.org/en/subtitles/4119493/24-day-4-7-00-a-m-8-00-a-m-en',
                        'IDMovie' => '73012',
                        'SeriesSeason' => '4',
                        'SubHD' => '0',
                        'SubLanguageID' => 'eng',
                        'MovieImdbRating' => '8.5'
                      }
                    ]
        };

我发现我很难将我的头脑围绕在键上,因为我来自一种没有像哈希这样的编程语言。能否请您告诉我代码有什么问题?

我应该提一下,虽然我使用了严格和警告,但相同的代码在 Windows 中运行的 Activestate perl 5.16.3 上编译得很好,而在 Debian 上运行的 perl 5.14.2 中编译失败。

编辑:我已经根据 Dumper 的数据更新了 $result 的内容。

【问题讨论】:

  • $result->{data} 是一个数组,而不是哈希。哈希在$result->{data}[0]
  • 嗯..这如何解释相同的代码如何在一个 perl 版本而不是另一个版本中工作。
  • 那部分我无法解释。
  • 你能告诉我们use Data::Dumper; print Dumper($result)的输出吗?您显示的结果不是语法上有效的 Perl 数据结构。
  • @Slade 甚至use Data::Dump; dd $result,更容易阅读,但需要安装 CPAN。

标签: perl hash


【解决方案1】:

我建议您不要在标量或数组上使用keys。 Perl perldoc(重点是我的):

从 Perl 5.14 开始,keys 可以采用标量 EXPR,它必须包含对 unblessed 哈希或数组的引用。该参数将被自动取消引用。 keys 的这一方面被认为是高度实验性的。 在 Perl 的未来版本中,确切的行为可能会发生变化。

   for (keys $hashref) { ... }
   for (keys $obj->get_arrayref) { ... }

相反,只需在哈希上使用它,如下所示:

foreach my $key ( keys %{$result->{data}[0]} ) {

【讨论】:

    【解决方案2】:

    keys 函数需要一个有效的散列(或数组,在 5.12 或更高版本中)作为其参数。在 5.14 中引入了一个实验性功能,其中几个这样的数组/哈希函数(包括 keyspush 和其他)将隐式尝试取消引用标量表达式,这将允许您执行以下操作:

    my $hash_ref = { foo => 1 };
    print keys $hash_ref;
    

    而不是显式取消引用:

    my $hash_ref = { foo => 1 };
    print keys %{ $hash_ref };
    

    但是,此功能被认为是高度实验性的*,可能会在未来的版本中被删除。有效使用它(例如上面的示例)将产生警告:

    keys on reference is experimental at ... line ...
    

    无效的使用会产生你得到的错误:

    my $foo = "This is not a hash ref";
    print keys $foo;
    

    Type of argument to keys on reference must be unblessed hashref or arrayref at -e line 1.

    *Experimental 在 Perl 特性方面具有官方含义。任何标记为实验性的功能都可能在没有进一步警告的情况下被删除和/或破坏向后兼容性的更改。

    解决您的问题的方法是不要在标量表达式上使用keys。这意味着您需要适当地取消引用您的数据结构访问,以便 keys 的参数是一个数组或哈希变量。如果我没有误解您编写结构的方式,语法将类似于:

    foreach my $key (keys %{ $result->{data} }) { ... }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-18
      • 1970-01-01
      • 2017-07-13
      • 1970-01-01
      • 1970-01-01
      • 2021-01-19
      相关资源
      最近更新 更多