假设我有一个日志文件,其中包含描述某些事件的行。 E.g:
15.03.2014 (14:23) Thing #25 deleted, user @david, session #45
15.03.2014 (15:00) Thing #26 created, user @alex, session #54
...
我可以使用grep
轻松提取独立事件 - 即使我不知道有关事件的所有信息,它也能正常工作。
但我想进一步调查相关事件。请考虑日志中的以下行:
15.03.2014 (14:23) Thing #25 created, user @david, session #45
...
17.03.2014 (15:00) Thing #25 deleted, user @david, session #54
我想仅在Thing #X created, user @Y, session #Z
事件成功后才搜索Thing #X deleted, user @Y, session #M
事件,其中M和Z不同。
当然,我可以在5-10行代码中执行此操作:搜索第一种类型的事件,获取所有后续行,搜索第二种类型的事件,过滤。
但也许有一些工具可以解决这个问题,我会重新发明这个问题吗?
答案 0 :(得分:1)
Perl是一个非常强大的工具,适用于这些类型的任务,并且可以使用单行处理它,如下所示:
cat txt | perl -n -e 'if (m^Thing #(\d+).*? (created|deleted).*? user @(\S+),.*? session #(\d+)^) { my $id = "$3.$1"; if ($2 eq "created") { @db{$id} = [$4,$_] } else { if (exists($db{$id}) && $db{$id}[0] != $4) { print $db{$id}[1]."$_" } delete @db{$id} } }'
为了便于阅读,这里的内容与shell脚本相同:
#!/usr/bin/perl
while (<>) {
if (m^Thing #(\d+).*? (created|deleted).*? user @(\S+),.*? session #(\d+)^) {
my $id = "$3.$1";
if ($2 eq "created") {
@db{$id} = [$4,$_]
} else {
if (exists($db{$id}) && $db{$id}[0] != $4) {
print $db{$id}[1]."$_"
}
delete @db{$id};
}
}
}
这将打印出创建/销毁线对,其中给定用户创建并销毁具有不同会话ID的特定事物。
请注意,该脚本假定“&#39; Thing&#39;标识符是特定于用户的,并且处理一个用户创建Thing X而另一个用户将Thing X作为单独的东西销毁的情况(如果这不是真的并且用户共享Things,则将$ id更改为&#34; $ 1&#34;)。它还假设每次创建时最多会销毁一次物品(如果每次创建可以删除多次,则删除删除行)。显然我没有您的实际输入文件,因此您可能需要调整正则表达式以匹配实际格式。
这种方法可能比执行OP中建议的多次搜索要好得多,因为它只需一次通过日志而没有临时文件;因此,对于非常大的日志文件,它可能更有效/更合适。内存利用率随着“事物”的数量而变化。除非你的日志有大量非常长寿的东西,否则它应该是合理的。