我有一个很长的日志文件,我试图摆脱包含foo disconnected
的所有行,但没有包含foo has connected.
的伴随行,这些行将在断开连接消息之前。关于这一点的棘手部分是该文件可以包含来自同一用户的多个断开连接消息,这些消息具有先前的连接消息,并且所有这些消息将在错误的断开连接消息之前。
例如,在此示例文件中,我想删除第4行,第6行和最后3行。
user1 has connected.
BigDaddy has connected.
user1 disconnected
foobar123 disconnected
user1 has connected.
noobmaster disconnected
user1 disconnected
BigDaddy disconnected
BigDaddy has connected.
user1 disconnected
user1 disconnected
user1 disconnected
答案 0 :(得分:1)
保留已连接用户的哈希值
该程序期望输入日志文件的路径作为命令行上的参数
use strict;
use warnings;
my %connected;
while ( <> ) {
my ($user, $action) = split ' ', $_, 2;
if ( $action =~ /disconnected/i ) {
next unless $connected{$user};
$connected{$user} = 0;
}
elsif ( $action =~ /connected/i ) {
$connected{$user} = 1;
}
print;
}
user1 has connected.
BigDaddy has connected.
user1 disconnected
user1 has connected.
noobmaster disconnected
BigDaddy has connected.
user1 disconnected
在Perl中编写简洁的难以理解的代码并非不可能。这是the awk solution from chepner的转换。它具有与上面相同的输出,但请注意我对他的解决方案的评论中的疑虑
perl -n -e'
($u) = /(\S+)/;
$arr[$u] = 1 if /has conn/;
print if $arr[$u];
$arr[$uarr[$1]] = 0 if /disconn/
' tmp.txt
答案 1 :(得分:0)
在awk
中,使用数组来跟踪哪些用户有活动连接。
awk '/has conn/ { arr[$1]=1; }
arr[$1] {print}
/disconn/ {arr[$1]=0}' tmp.txt
请注意,我们会检查arr[$1]
之前的值在断开的行上禁用它,以便仍然打印第一行连续行。
答案 2 :(得分:0)
my @lines = <DATA>;
my %status = ();
foreach my $line (@lines) {
my ($user) = $line =~ /([A-Za-z0-9]+)\s+/;
#User has connected and not defined or disconnected
if($line =~ /has connected/ && !$status{$user}){
$status{$user} = 1;
print $line;
}
# Connected user disconnected.
elsif($line =~ /disconnected/ && $status{$user}){
$status{$user} = 0;
print $line;
}
}
答案 3 :(得分:-1)
使用perl:
open FILE, "<disconnect.txt" or die $!;
my @lines = <FILE>;
close FILE or die $!;
my @connectedusers = ();
foreach $line(@lines) {
# if connected, then push user name to array
if($line =~ /(\w+) has connected/) {
push(@connectedusers, $1);
print $line;
# if disconnected, then check whether user name is in array
} elsif ($line =~ /(\w+) disconnected/) {
my $idx = 0;
foreach(@connectedusers) {
if(/$1/) {
# remove user name from array
splice(@connectedusers, $idx, 1);
print $line;
}
$idx++;
}
}
}