【问题标题】:How can i do a grep count by using timestamp如何使用时间戳进行 grep 计数
【发布时间】:2012-12-06 23:41:24
【问题描述】:

如何使用时间戳计算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

我想找出xyz20121912-08:15:55 之后出现的次数,在这种情况下应该是2

执行grep -c "xyz" filename 会读取整个文件并给出结果。我想在最后一次更新之后或使用时间戳来完成。

【问题讨论】:

  • 时间戳格式的不幸选择。

标签: bash shell unix terminal grep


【解决方案1】:

试试这个单线:

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

【讨论】:

  • 不知道 awk 会解析和比较时间戳;非常整洁的一个!
  • 日期不是按字典顺序降序排列的,例如20122011-08:15:55 比 20121912-08:15:55 “更大”。
  • @Rubens:不,它不起作用,awk 将执行字符串比较,在这种情况下,它与日期比较不同。如果日期格式为:YYYYMMDD-HH:MM:SS。
【解决方案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

【讨论】:

    【解决方案3】:

    这是一种 hack,但只是 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个问题:a,如果文件没有按时间戳排序会怎样? b,以 20121912-08:10:10 开头的行怎么样? c、如果20121912-08行后面有很多很多行怎么办?
    【解决方案4】:

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

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

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

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

    【讨论】:

      【解决方案5】:

      从 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}
      '
      

      【讨论】:

        【解决方案6】:

        嗯,快写一篇:

         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

        【讨论】:

        • 投反对票很好,解释时...?
        猜你喜欢
        • 1970-01-01
        • 2016-08-07
        • 1970-01-01
        • 2012-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-28
        相关资源
        最近更新 更多