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

时间:2021-03-10 21:23:13

I use grep to return unmatched array between temporaryF file and arrayWarning

我使用grep在temporaryF文件和arrayWarning之间返回不匹配的数组

my @c =grep!${{map{$_,1}@temporaryF}{$_},@arrayWarning;

Inside @c there are alot of lines for example:

在@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  

as you can see ROOT occurs 3 times in @c. How can I iterate through @c to output only the latest occurrence of ROOT -> Sun Sep 30 00:10:55 fibre channel ROOT and not the other repeated lines.

你可以看到ROOT在@c中发生了3次。如何迭代@c只输出最新出现的ROOT - > Sun Sep 30 00:10:55光纤通道ROOT而不是其他重复行。

so it will become:

所以它会变成:

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 个解决方案

#1


3  

Note: this is an extension of the answer of @RobEarl - so if you like it, please make sure to give him credits, too!

注意:这是@RobEarl答案的延伸 - 所以如果你喜欢它,请务必给予他学分!

The point here is to store the line count too, to make sure the output can be ordered.

这里的重点是存储行数,以确保可以订购输出。

Long version

#!/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  

Output:

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  

Feels a little bit like the Schwartzian transform.

感觉有点像Schwartzian变换。

One-liner version

This is an excellent example for a task that can be accomplished by a simple oneliner with perl's powerful interpreter switches:

对于可以通过perl强大的解释器开关的简单oneliner完成的任务,这是一个很好的例子:

$ 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  

Output:

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  

Use a hash with ROOT/DENY/DANN as the key:

使用以ROOT / DENY / DANN为键的哈希:

my %latest = map { (split(" "))[6] => $_ } @c;

Assuming @c is ordered by date, values %latest will contain:

假设@c按日期排序,值%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

#1


3  

Note: this is an extension of the answer of @RobEarl - so if you like it, please make sure to give him credits, too!

注意:这是@RobEarl答案的延伸 - 所以如果你喜欢它,请务必给予他学分!

The point here is to store the line count too, to make sure the output can be ordered.

这里的重点是存储行数,以确保可以订购输出。

Long version

#!/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  

Output:

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  

Feels a little bit like the Schwartzian transform.

感觉有点像Schwartzian变换。

One-liner version

This is an excellent example for a task that can be accomplished by a simple oneliner with perl's powerful interpreter switches:

对于可以通过perl强大的解释器开关的简单oneliner完成的任务,这是一个很好的例子:

$ 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  

Output:

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  

Use a hash with ROOT/DENY/DANN as the key:

使用以ROOT / DENY / DANN为键的哈希:

my %latest = map { (split(" "))[6] => $_ } @c;

Assuming @c is ordered by date, values %latest will contain:

假设@c按日期排序,值%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