Arrays perl放弃映射操作中的第一个数组元素
我开始利用perl map的强大功能,遇到了一个我找不到答案的问题。基本上,我正在解析一个unix命令的返回,该命令有一个我不需要的标题行,然后每个项目有两行信息。目前,我正在这样做:Arrays perl放弃映射操作中的第一个数组元素,arrays,perl,map,slice,splice,Arrays,Perl,Map,Slice,Splice,我开始利用perl map的强大功能,遇到了一个我找不到答案的问题。基本上,我正在解析一个unix命令的返回,该命令有一个我不需要的标题行,然后每个项目有两行信息。目前,我正在这样做: (undef, @ret) = map { [split /\n/] } split(/(?:Host: )/, `cat /proc/scsi/scsi`); 跳过标题并为每行“有用”文本提供一个数组元素,这样做很好。然而,我想构建一个散列,除了那个额外的行之外,我知道怎么做。那么,我如何在一行代码中忽略第一
(undef, @ret) = map { [split /\n/] } split(/(?:Host: )/, `cat /proc/scsi/scsi`);
跳过标题并为每行“有用”文本提供一个数组元素,这样做很好。然而,我想构建一个散列,除了那个额外的行之外,我知道怎么做。那么,我如何在一行代码中忽略第一个数组元素,从而创建哈希呢?我想在切片或拼接的某个位置,但我需要知道主机上拆分创建的阵列的大小(可能吗?)。我想我也可以做一个(undef,undef,%ret)=映射{…},但是如果这可以通过切片或拼接来完成,那将是非常好的学习方法。嘿,好吧,看起来确实和我想的一样简单,我刚刚忘记了-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`));
正如@ThisSuiteisBlacknot所指出的,我仍然需要解决主机clobberin的时间问题,但这对我的问题来说并不紧迫,而且应该是直接的,如果不是琐碎的话。从一个状态变量中删除第一个元素并仍然能够链接更多命令的一种方法是与一个状态变量一起使用:
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来读取该文件,而不是使用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>
};
使用严格;
使用警告;
使用自动模具;
我的%hash=do{
打开我的$fh,'小心,
[1,-1]只返回第二个和最后一个元素。哦,嗯..那么我不知道该怎么做。只需像第一个atempt那样做,或者分两行:@ret=map…;shift@ret;
然后将其包装成一个数组:拼接(@{[1..7]},1,-1)
但是这样就可以去掉第一个和最后一个元素;没有办法告诉片到片的末端。你必须选择一个任意大的数拼接(@{[1..7]},199999999)
或者添加一个伪元素拼接(@{[1..7,undef]},1,-1)
分配给(undef,undef,%hash)那就更好了。哦,你是说匿名数组?不要太过拘泥于“在一行代码中”做事与笨拙地将代码强制放在一行中相比,目的明确的可读代码更容易维护。要将配置文件读入哈希,通常最好是打开
该文件,并在while
循环中读取内容,边走边处理。在这种情况下,哈希键要使用什么?我将使用e主机号作为键。虽然我试图在一行中完成这项工作,但我的愿望主要是学习如何获取跳过某些元素的列表(而不是数组)切片。这不起作用,因为多个设备可以共享同一主机。你的意思是,它们可以使用同一主机,但位于不同的通道上?对于我当前的(简单)这不会成为问题的应用程序,因为它只是为了添加主机,所以主机就是我所需要的。请查看on/proc/scsi
中的示例文件。如果您仅使用散列来获取唯一的主机名,则该方法会起作用;否则,您需要选择不会破坏散列中现有密钥的内容。请注意使用在grep
内部的state
(和map
等)。它只初始化一次,因此如果grep
多次运行(例如,多次调用函数),您可能无法得到您希望的结果。请尝试以下操作:执行{grep{state$line=0;$line++;print$line,}0..1}对于0..1;
您将得到“1 2 3 4”,而不是“1 2 1 2”。是的,我只是在一个单一使用脚本的上下文中提供了一个选择,而不是作为一个可重用的函数调用。但是,我继续并重新编写了它,因为我不想对糟糕的技术建模,特别是因为我主张无论如何都不要执行链式命令。grep{++$line>1},和do{}是非常有趣和有用的方法,谢谢。