perl在map操作中丢弃第一个数组元素

时间:2014-08-12 17:15:05

标签: arrays perl map slice splice

我开始利用perl地图的强大功能,遇到了一个我无法找到答案的问题。基本上我正在解析一个unix命令的返回,它有一个我不需要的标题行,然后是每个项目的2行信息。目前,我这样做:

(undef, @ret) = map { [split /\n/] } split(/(?:Host: )/, `cat /proc/scsi/scsi`);

可以跳过标题并为每个“有用”文本行提供一个数组元素。但是,我想构建一个哈希,我知道除了额外的行之外该怎么做。那么我怎样才能在一行代码中忽略第一个数组元素,允许我创建哈希?我正在考虑切片或拼接线的某处,但我需要知道主机上的拆分创建的数组的大小(可能吗?)。我想我也可以做一个(undef,undef,%ret)= map {...}但是如果可以用切片或拼接来完成,那么学习如何做是很好的。

2 个答案:

答案 0 :(得分:4)

split中移除第一个元素并且仍能够链接更多命令的一种方法是将grep与状态变量一起使用:

use strict;
use warnings;

my @lines = do {
    my $line = 0;
    grep {++$line > 1} split /\n/, "1\n2\n3\n4\n5\n6\n7\n"
};

print "@lines";

输出:

2 3 4 5 6 7

但是,我认为你试图在一行代码中做太多。

由于看起来您只是在阅读文件,我建议您使用Perl open文件,而不是炮轰cat

假设您的键/值分隔符是冒号,以下是我建议您构建逻辑的方法:

use strict;
use warnings;
use autodie;

my %hash = do {
    open my $fh, '<', '/proc/scsi/scsi';
    <$fh>; # Skip Header Row
    map {chomp; split /:/, $_, 2} <$fh>
};

答案 1 :(得分:0)

嘿,好吧,看起来它确实像我想的那么容易,我刚刚忘记了-1索引位置,所以,对于任何可能有兴趣做这样的事情的人的解决方案是:

@ret = map { [split /\n/] } (split(/(?:Host: )/, `cat /proc/scsi/scsi`))[1,-1];

让它跳过主机上拆分返回的第一个数组元素。


(以上是完全错误的,正如@ M42指出的那样,仅供参考。)

对于那些感兴趣的人,这是我提出的最终代码(基于@Miller的糟糕方法,有一些简化)来解决我的问题:

my $i;
my $split_RE = qr(\S+|ANSI  SCSI revision); # you can create the precise list of keys here
my %attached = map {
        chomp;
        my ($host, %infohash) = split(/\s*($split_RE):\s*/);
        ($host => {%infohash} ) # FIXME: one host can have multiple devices.. an array with push() needs to be used here.. somehow (might have to avoid use of map)
        } 
    grep{$i++} # remove/ignore first line
    (split(/(?:Host: )/, `cat /proc/scsi/scsi`));

我仍然需要解决主机clobberin&#39;时间,正如@ThisSuitIsBlackNot所指出的那样,但这对我的问题并不紧迫,如果不是微不足道的话应该是直截了当的。