如何使用时间戳进行grep计数

时间:2012-12-19 15:19:35

标签: bash shell unix terminal grep

如何使用时间戳进行grep计数?

示例:如果我有一个文件,我每次都会搜索值xyz。该文件定期更新。

20121912-07:15:55 abc cbfr xyz
20121912-07:16:40 mni cbfr xyz
-----------
-----------
-----------


20121912-08:15:55 gty cbfr xyz
20121912-08:20:55 jui uio xyz

我想了解xyz之后20121912-08:15:55的出现情况,在这种情况下应该是2

执行grep -c "xyz" filename读取整个文件并给出结果。我希望在上次更新或使用时间戳后执行此操作。

6 个答案:

答案 0 :(得分:2)

试试这个单行:

awk '$NF=="xyz"&&$1>="20121912-08:15:55"{x++;}END{print x}' file

答案 1 :(得分:2)

我假设你想找到模式的出现:'xyz',其中日期/时间值大于或等于指定的日期/时间:'20121912-08:15:55'。这是我使用GNU awk做的事情。像:

一样运行
awk -v pattern="xyz" -v time="20121912-08:15:55" -f script.awk file

script.awk的内容:

BEGIN {
    stamp = convert(time)
}

$0 ~ pattern && convert($1) >= stamp {
    i++
}

END {
    print i
}

function convert(var) {

    x = "(....)(..)(..)-(..):(..):(..)"
    y = "\\1 \\3 \\2 \\4 \\5 \\6"

    return mktime(gensub(x,y,"",var))
}

结果:

2

或者,这是单行:

awk -v pattern="xyz" -v time="20121912-08:15:55" 'BEGIN { stamp = convert(time) } $0 ~ pattern && convert($1) >= stamp { i++ } END { print i } function convert(var) { return mktime(gensub(/(....)(..)(..)-(..):(..):(..)/,"\\1 \\3 \\2 \\4 \\5 \\6","",var)) }' file

答案 2 :(得分:1)

对于您想要的最早日期,这只是一种黑客攻击,只有grep,然后使用-A打印所有行,然后通过管道传输到grep -c xyz

$ fgrep -A 100 '20121912-08:15:55' file | fgrep -c 'xyz'
2

注意:fgrep只是固定字符串grep,因为您没有使用regex模式,这与执行grep -F相同。

由于使用sed来打印日期中的所有行,所以不那么愚蠢,这样您就不需要确保-A的值会覆盖文件的长度:

$ sed -n '/20121912-08:15:55/,$p' file | fgrep -c 'xyz'
2

当然,假设您的文件按时间戳排序,如果它不是那么:

$ sort file | sed -n '/20121912-08:15:55/,$p' | fgrep -c 'xyz'
2

答案 3 :(得分:1)

您可以告诉sed从给定范围(起点和终点)的文件中打印行 - 该范围可以是正则表达式或行号表示法。

根据您的需要,应该这样做:

$ sed -n '/20121912-08:15:55/,$p' input.txt | grep -c xyz

此处起始点由日期给出,视为正则表达式,终点是最后一行符号$p告诉sed打印给定范围内的行。 sed的-n选项告诉它不打印它正在处理的行。

答案 4 :(得分:1)

从Kent的答案中汲取灵感,这里有一些Perl将奇怪的时间戳操作为YYYYMMDD格式:

ts="20121912-08:15:55" patt="xyz" perl -lane  '
    BEGIN {
        ($wanted_ts = $ENV{ts}) =~ s/^(....)(..)(..)/$1$3$2/;
        $pattern = qr{$ENV{patt}};
    }
    ($this_ts = $F[0]) =~ s/^(....)(..)(..)/$1$3$2/;
    $count++ if $this_ts ge $wanted_ts and /$pattern/;
    END {print $count}
'

答案 5 :(得分:0)

嗯,很快就写了一篇:

 grep xyz filename | sed -r 's/^([^ ]+).*/ 20121912-08:15:55 <= \1/' | sed -r 's/([0-9]{4})([0-9]{2})([0-9]{2})/\1\3\2/g' | sed 's/[-:]//g' | bc | grep 1 | wc -l

它非常丑陋(我不是sed也不是命令行大师)并且可能会缩短,但这是一种方法。说明如下:

  grep xyz filename                                  //gets all interseting lines
| sed -r 's/^([^ ]+).*/ 20121912-08:15:55 <= \1/'    //transform them into 
                                                       //comparison with the 
                                                       //date you want
| sed -r 's/([0-9]{4})([0-9]{2})([0-9]{2})/\1\3\2/g' //invert day and month
| sed 's/[-:]//g'                                    //remove separators
| bc                                                 //ask bc result 
| grep 1                                             //get true results only
| wc -l                                              //and finally count them

对于您示例的最后一行,步骤将给出:

20121912-08:20:55 jui uio xyz                  //grep 'xyz'
20121912-08:15:55 <= 20121912-08:20:55         //sed
20121219-08:15:55 <= 20121219-08:20:55         
20121219081555 <= 20121219082055               
1                                              //result from bc

HTH