Perl - 将数组元素句子与变量进行比较

5
我使用grep命令返回临时文件temporaryF和警告数组arrayWarning之间不匹配的数组。
my @c =grep!${{map{$_,1}@temporaryF}{$_},@arrayWarning;

在@c中有很多行代码,例如:

Sun Sep 30 00:05:55 fibre channel DENY forever
Sun Sep 30 00:06:55 fibre channel ROOT cause
Sun Sep 30 00:08:55 fibre channel ROOT cause 
Sun Sep 30 00:10:55 fibre channel ROOT cause  
Sun Sep 30 00:20:55 fibre channel DANN 
Sun Sep 30 00:30:55 fibre channel DANN  

正如您所看到的,@c 中出现了3次 ROOT。我该如何遍历 @c 并仅输出最新的 ROOT -> Sun Sep 30 00:10:55 光纤通道 ROOT,并排除其他重复的行。
因此,它将变成:
Sun Sep 30 00:05:55 fibre channel DENY forever  
Sun Sep 30 00:10:55 fibre channel ROOT cause  
Sun Sep 30 00:30:55 fibre channel DANN
2个回答

3
注意:这是对@RobEarl答案的扩展——如果您喜欢它,请确保也给他以荣誉!
重点在于存储行数,以确保输出可以排序。
长版如下:
#!/usr/bin/perl

use strict;
use warnings;

# store (with count)
my $count  = 0;
my %latest = map {
    my $source = (split /\s+/ => $_)[6];
    $source => {count => $count++, string => $_};
} <DATA>;

# output
print $_->{string} for sort {$a->{count} <=> $b->{count}} values %latest;

__DATA__
Sun Sep 30 00:05:55 fibre channel DENY forever
Sun Sep 30 00:06:55 fibre channel ROOT cause
Sun Sep 30 00:08:55 fibre channel ROOT cause 
Sun Sep 30 00:10:55 fibre channel ROOT cause  
Sun Sep 30 00:20:55 fibre channel DANN 
Sun Sep 30 00:30:55 fibre channel DANN  

输出:

Sun Sep 30 00:05:55 fibre channel DENY forever
Sun Sep 30 00:10:55 fibre channel ROOT cause  
Sun Sep 30 00:30:55 fibre channel DANN  

感觉有点像施瓦茨变换

一行版本

这是一个非常好的例子,可以通过Perl强大的解释器开关来完成简单的一行代码:

$ perl -nale '$l{$F[6]}={c=>$c++,s=>$_};END{print$_->{s}for sort{$a->{c}<=>$b->{c}}values%l}'
Sun Sep 30 00:05:55 fibre channel DENY forever
Sun Sep 30 00:06:55 fibre channel ROOT cause
Sun Sep 30 00:08:55 fibre channel ROOT cause 
Sun Sep 30 00:10:55 fibre channel ROOT cause  
Sun Sep 30 00:20:55 fibre channel DANN 
Sun Sep 30 00:30:55 fibre channel DANN  

输出:

Sun Sep 30 00:05:55 fibre channel DENY forever
Sun Sep 30 00:10:55 fibre channel ROOT cause  
Sun Sep 30 00:30:55 fibre channel DANN  

你好,能否请您发布一些关于您在代码中使用的 __XYZ__ 语言结构的信息?它有一个名称,这样我就可以搜索它吗?我以前从未见过它。 - duri
嗨@duri,我不确定这是否是开始的最佳perldoc,但我在perldata中找到了一些相关内容。这只是一种方便的方式,可以将程序和输入数据存储在一个脚本文件中。 :) - memowe
谢谢。抱歉离题了。 - duri
谢谢,这只有在警告词在(split /\s+/ => $)[6]之后才有效; 但是如何将其更改为substr($,20)?我似乎无法在您的代码中实现它。 - momokjaaaaa
没事了,我搞定了。我把它改成了 my $source = (substr($,20)); 在这之前是 my $source = (substr($,20) => $_); 所以出问题了。 - momokjaaaaa
显示剩余3条评论

3
使用哈希表,以ROOT/DENY/DANN为键:
my %latest = map { (split(" "))[6] => $_ } @c;

假设@c按日期排序,values %latest将包含:

Sun Sep 30 00:10:55 fibre channel ROOT cause
Sun Sep 30 00:05:55 fibre channel DENY forever
Sun Sep 30 00:30:55 fibre channel DANN

@c的排序对values %latest的顺序没有(明确定义的)影响,因为哈希表是无序的。 - memowe
@memowe 不会,但它确实会影响内容。 - RobEarl
没事了,你是对的,只有例如 ROOT 的“最新”出现才会被保留。但是,值列表并没有按日期排序,正如人们可能会认为的那样。 - memowe
我添加了一个可排序输出的答案扩展。 - memowe
@memowe,看起来不错。我本来想从@c(最后的grep)获取订单,但通过哈希表保留它可能更有意义。 - RobEarl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接