【问题标题】:Return reference to an array in Perl在 Perl 中返回对数组的引用
【发布时间】:2012-06-28 04:04:32
【问题描述】:

首先,让我告诉你,我很少使用数组,从未使用哈希。另外,Perl 不是我最强的脚本语言。我来自 shell 脚本的背景。

也就是说,我在 Perl 脚本中有这个:

$monitored_paths = { '/svn/test-repo'  => 'http://....list.txt' };

URL 指向一个文件,其中包含如下路径列表:

/src/cpp
/src/test
/src/test2

目标是用内容替换 URL:

$monitored_paths = {'svn/test-repo' => '/src/cpp', '/src/test', '/src/test2'}

实现这一目标的最佳方法是什么?谢谢!

山姆

【问题讨论】:

  • 哈希它只是一个使用字符串而不是数字索引的数组。

标签: arrays perl parsing url reference


【解决方案1】:

你的问题前提有错误,因为这行:

$monitored_paths = {'svn/test-repo' => '/src/cpp', '/src/test', '/src/test2'}

相当于以下任何一个:

$monitored_paths = {'svn/test-repo' => '/src/cpp', '/src/test' => '/src/test2'}
$monitored_paths = {'svn/test-repo', '/src/cpp', '/src/test', '/src/test2'}

你真正想要的是:

$monitored_paths = {'svn/test-repo' => ['/src/cpp', '/src/test', '/src/test2']}

其中 [] 表示数组引用。您可以像这样创建一个数组引用:

my $arrayref = [1, 2, 3]; # called an "anonymous array reference"

或者像这样:

my @array = (1, 2, 3);
my $arrayref = \@array; 

你想要这样的东西:

$monitored_paths = { '/svn/test-repo'  => 'http://....list.txt' }
foreach my $key (keys %$monitored_paths) {
    next if ref $monitored_paths{$key} eq 'ARRAY'; # skip if done already
    my @paths = get_paths_from_url($key);
    $monitored_paths->{$key} = \@paths; # replace URL with arrayref of paths
}

将 get_paths_from_url 替换为您的 URL 获取和解析功能(使用 LWP 或其他...因为这不是您的问题的一部分,我假设您已经知道如何做到这一点)。如果您编写函数 get_paths_from_url 以首先返回数组引用而不是数组,则可以保存一个步骤并改写$monitored_paths->{$key} = get_paths_from_url($key)

【讨论】:

  • 太棒了!是的,我同意我没有正确提出我的问题。对于那个很抱歉。是的,我已经想办法让 LWP 从 URL 中获取内容。我会给你的代码一个镜头。谢谢!
  • 无需道歉,只是描述正确的语法。如果有效,请接受答案。
  • 恐怕我无法让它工作。 $monitored_pa​​ths 是常规路径和 URL 的混合。因此,需要避免使用 foreach 在所有项目上运行它。我需要在 foreach 之后放置一个“if ref ...”,但不能完全得到要检查的语法。另外,假设一切顺利,我最后如何打印 $monitored_pa​​ths 的内容?在 get_paths_from_url 函数中,当我打印 $ARGV[0] 的内容时,我会在屏幕上多次获得 /svn/test-repo。理想情况下,它应该是 URL。 :(
  • 很多问题... 1. 当它不是 URL 时,我不知道你想做什么。用next if $monitored_paths{$key} =~m/^http/; 跳过它 2. 你可以用use Data::Dumper; print Dumper($monitored_paths); “打印内容” 3. @ARGV 用于命令行参数,子程序参数传递给@_(所以第一个参数是$_[0],第二个是$ _[1])。希望对您有所帮助。
  • 是的,我认为我可以使用匹配子字符串 http。那应该行得通。明天我会先试一试。如果没有 http:,那么我们就跳过它。我也会按照您的建议尝试 Data::Dumper。我尝试以其他各种方式使用它,但没有成功。再次感谢! :)
【解决方案2】:

如果您想从文件中读取并将每个路径添加到数组中,您可以 做类似的事情:

use strictures 1;

my $monitored_paths = {};
open( my $FILE, '<', '/path/to/file' ) or die 'Unable to open file '. $!;
while($FILE){
    push @{ $monitored_paths->{'svn/test-repo'} }, $_;
}

【讨论】:

  • 有趣。实际上,monitored_pa​​ths 除了 URL 之外还有很多其他的引用。我可以将您的代码添加到堆栈之上吗?
  • 当然。如果您转储监控路径变量,您将看到“svn/test-repo”和路由。如果您需要更多键,只需根据条件将它们推到不同的键上。 print Dumper($monitored_pa​​ths);
  • 那行不通,因为$monitored_paths-&gt;{'svn/test-repo'} 的值还不是数组引用,你不能推动它。您可以在推送之前使用 ref() 添加检查,如果 ref() 为 false,则将其设置为 []。
【解决方案3】:
use LWP::Simple;
my $content = get($url); ## do some error checking
$monitored_paths = {'svn/test-repo' => [split( "\n", $content)]}

【讨论】:

  • 不,这是不可能的。我无法对路径进行硬编码。它们必须驻留在 URL 中,并且必须在运行时读取。
  • 使用原始哈希查找 URL 并对这些 URL 执行获取并创建新哈希。
【解决方案4】:
use LWP;
foreach (keys %monitored_paths)
{
   my  $content = get($monitored_paths{$_});# Perform error checking
   $monitored_paths_final {$_} = join(",",split("\n",$content));
}

【讨论】:

  • 该代码中存在一个错误,它每次都会创建一个新的 hashref 并将其分配给 $monitored_pa​​ths_final。您最终将只有一个键(循环中的最后一个)。
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 2018-03-24
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 2016-04-21
相关资源
最近更新 更多