2011-10-04 50 views
1
[2011-09-23 18:46:51:697 GMT+00:00][17B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedOut #mouseclicked# userid=1 
[2011-09-24 19:46:53:697 GMT+00:00][47B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedOut #mouseclicked# userid=12 
[2011-09-25 20:46:51:697 GMT+00:00][57B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedin #mouseclicked# userid=23 
[2011-09-25 20:46:51:697 GMT+00:00][57B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] DEBUG mouseclicked by userid=566 
[2011-09-25 20:56:56:697 GMT+00:00][77B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedin #mouseclicked# userid=44 
[2011-09-26 22:48:55:697 GMT+00:00][87B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedOut #mouseclicked# userid=55 

在上面的文件中,我想知道在从9月24日到11月25日(包括两个日期)的日期范围内发生了多少次#mouseclicked#。Unix grep查询

在上述情况下,命令应返回我3(注:是的mouseClicked不考虑,因为它不是以#匹配的mouseClicked#)

我怎么能在这种情况下使用grep命令?

+0

grep的通过线工作线,所以日期限制是有点棘手。我猜,你可以grep for'mouseclicked'并将结果排序为开头,但是也许不同的工具会更有用(可能是Perl?)。 –

回答

3

grep孤单不会解决一般问题。它无法识别在特定日期范围内的线条。 (嗯,这大概可以,如果你使用一个足够复杂的正则表达式,但正则表达式将是约会,你有兴趣的每个范围完全不同。)

但是对于您的具体问题,这将工作:

egrep -c '^\[2011-09-(24|25).*#mouseclicked#' filename 

egrep支持更强大的正则表达式形式,包括|运算符。 -c选项告诉它打印匹配行的数量,而不是自己打印行。

但是,正如你可以想象的那样,如果你想从9月30日下午1点到10月2日上午11点的线条,正则表达式会变得更加复杂,并且构建它需要一些重要的努力。

如果我打算做这个有很多,我会写一个单独的工具,它可以提取日期的指定范围内的行(或日期和时间),同时在该文件中使用的特定日期格式的优势( YYYY-MM-DD HH:MM:SS,ISO-8601是一个很好的选择)。就我个人而言,我会用Perl编写这样一个工具。然后我可以在该文件上运行该工具并通过grep管道输出。

编辑

在回应评论,grep不明白日期范围,只是字符序列。您可以编写一个复杂的正则表达式,以匹配2010年10月1日至2011年1月1日范围内的所有内容。这是我尝试(未测试):

egrep -c '^\[(2010-1.*|2011-(0.|10|11)|2011-12-01).*#mouseclicked#' filename 

这涉及几个单独的子范围:通过2010年1月的月,月到九月,那么十月,那么2011年11月,终于2011年

12月1日

而且,正如我上面所说的,任何其他日期范围(或更糟的是,日期和时间),你需要构建符合所需的时间跨度子范围的全新复杂的正则表达式的基础上,他们的文字表述,而不是日期的含义。

这就是为什么我不会考虑这种方法,如果我想要做的不是一次或两次,这更。

你知道像Perl或Python这样的脚本语言吗?如果是这样,编写一个实际上可以解析时间戳并选择所需范围内的行的脚本不会太困难。

事实上,如果这样的工具已经存在(我只是不知道在哪里可以找到它),我一点也不会感到惊讶。

编辑2

这里是一个Perl脚本,我扔在一起:

#!/usr/bin/perl 

use strict; 
use warnings; 

die "Usage: $0 start end [file...]\n" if scalar @ARGV < 2; 
my $start = shift; 
my $end = shift; 
$start =~ s/\D//g; 
$end =~ s/\D//g; 
$end .= '99999999999999999999999999999'; 

print "start=\"$start\", end=\"$end\"\n"; 

while (<>) { 
    if (/^\[([^]]+)\]/) { 
     my $timestamp = $1; 
     $timestamp =~ s/\D//g; 
     if ($timestamp ge $start and $timestamp le $end) { 
      print; 
     } 
    } 
} 

它把指定的开始和结束时间,以及该文件中的时间戳,作为数字序列和对它们进行一个字符串(非数字)比较。它忽略了时区信息。使用CPAN的时间和日期模块可以使其更加复杂。

对于你原来的问题,你会运行:

this-perl-script 2011-09-24 2011-09-25 input-file | grep -c '#mouseclicked#' 
+0

如何使用上述命令给出日期范围,例如从2010年10月1日至2011年1月1日? – Mike

0

我会尝试类似 grep | wc -l

grep将过滤包含您的字符串的喜欢,而wc -l将计算grep输出的行数。

+0

'grep -c'比较简单。 –

1
cat filename | grep '^\[2011-09-2[45]' | grep mouseclicked | wc -l 

或者更简单地说:

grep '^\[2011-09-2[45]' filename | grep -c mouseclicked 
+2

'cat'和'wc -l'都是不必要的。而且你需要逃避'['所以'grep'不认为它是字符范围的开始。 –

+0

同意!我没有逃脱第一个'[':-)感谢输入 – 2011-10-04 23:54:32

+0

不,你没有逃脱第一个'[';我做到了。 –