【问题标题】:How can I join a nested Perl hash?如何加入嵌套的 Perl 哈希?
【发布时间】:2014-12-01 22:41:34
【问题描述】:

我有一个 Perl 哈希,用于存储有关 LUN 的信息。它的结构如下:

my %luns = (
    360000 => {
        Devices => [
            {   Major_Minor  => "8:144",
                SCSI_Address => "1:0:0:8",
                SCSI_Device  => "sdj",
                SCSI_Host    => "host1",
            },
            {   Major_Minor  => "129:48",
                SCSI_Address => "3:0:0:8",
                SCSI_Device  => "sder",
                SCSI_Host    => "host3",
            },
        ],
        DM_Device => "dm-13",
        Size      => "45G",
        WWID      => 360000,
    },
    360001 => {
        Devices => [
            {   Major_Minor  => "70:144",
                SCSI_Address => "1:0:1:39",
                SCSI_Device  => "sddb",
                SCSI_Host    => "host1",
            },
            {   Major_Minor  => "135:48",
                SCSI_Address => "3:0:1:39",
                SCSI_Device  => "sdij",
                SCSI_Host    => "host3",
            },
        ],
        DM_Device => "dm-53",
        Size      => "200G",
        WWID      => 360000,
    },
);

如何使用join 获取所有SCSI_Devices(例如360000)的逗号分隔列表?

【问题讨论】:

  • @JonesK:我已经回滚了您对该问题的编辑,因为我没有看到一个很好的理由并且您没有添加任何解释。自动提供的“在正文中添加了 22 个字符;已编辑标题”还远远不够,而且您的修改英文不好。 ——

标签: perl csv hash


【解决方案1】:

您正在使用哈希数组的哈希值。要了解如何使用此类结构,我建议阅读 perldsc - Perl Data Structures Cookbook

在这种情况下,以下循环将打印出您的每个设备列表:

for my $id ( sort { $a <=> $b } keys %luns ) {
    my @devices = map { $_->{SCSI_Device} } @{ $luns{$id}{Devices} };
    print "$id - @devices\n";
}

输出:

360000 - sdj sder
360001 - sddb sdij

Live Demo

【讨论】:

    【解决方案2】:

    你说你想要一个 LUN 360000 的值列表,所以首先你需要

    $luns->{36000}
    

    这是另一个带有Devices 元素的散列,它有一个数组引用 作为值,以及DM_DeviceSizeWWID 元素,它们的值是简单的标量.

    所以大概你想要的列表是

    $luns->{36000}{Devices}
    

    这是一个对哈希的引用数组,每个哈希都有Major_MinorSCSI_AddressSCSI_DeviceSCSI_Host元素。

    听起来您想要SCSI_Device 元素,而map 是帮助您解决此问题的理想工具

    my @scsi_devices = map { $_->{SCSI_Device} } @{ $luns->{360000}{Devices} };
    

    最后一步是一个很大的飞跃,它可能有助于在您的代码中将其分开。例如,您可以将引用复制到360000 的设备列表中,如下所示

    my $devices = $luns->{360000}{Devices};
    

    并从该数组中的每个哈希中提取SCSI_Device

    my @scsi_devices = map { $_->{SCSI_Device} } @$devices;
    

    无论哪种方式,数组引用都必须取消引用,并且必须从该数组中的每个哈希中提取所需的元素。

    要获取 CSV 记录,除非数据可能包含双引号的逗号,否则您只需将join 的结果map

    print join(',', @scsi_devices), "\n";
    

    输出

    sdj,sder
    

    虽然我认为这不能满足您的实际需要。如果不清楚,请询问。

    【讨论】:

    • 我用它作为一个衬里:print join(',', map { $_-&gt;{SCSI_Device} } @{ $luns-&gt;{360000}{Devices} };
    • 好的,但是我错过了你想要 CSV 格式的结果的观点。我已添加到我的解决方案中进行解释,但如果数据本身包含特殊字符(如逗号、引号或在某些情况下为空格),则必须小心。
    • 那行得通。目前尚不清楚您对数据的访问可能有多大的变化,或者您是否想要一个垂直切片而不是哈希列表上的水平切片。我很高兴它对你有用。
    • @JonesK 欢迎来到 SO。请记住,如果此答案解决了您的问题,请打勾。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 2011-02-14
    • 2020-12-09
    • 2016-09-05
    • 2012-11-27
    • 1970-01-01
    • 2011-10-04
    相关资源
    最近更新 更多