如何使用Bash在两个时间戳之间搜索文件中的行

时间:2014-05-16 14:34:16

标签: bash

在bash中,我正在尝试读取日志文件,并且只打印具有两个特定时间之间的时间戳的行。时间格式为hh:mm:ss。例如,我将搜索在12:52:33到12:59:33之间的行。

我想使用正则表达式,因为我可以在grep函数中使用它。

每个日志行都以some_nr 2014-05-15 21:58:00,000000 rest_of_line开头。

我的解决方案为我提供了1分钟的保证金。我删除了ss并使用hh:mm:[0-9]{2}占据所有行。 $ 2的格式为filename_hh:mm:;,例如:"24249_16:05:;24249_16:05:;24249_16:07:;24249_16:07:;24249_16:08:"

我的代码:

B=$2  

for line in ${B//;/ } ;
do  
    TENT=`echo $line | awk '{split($0,numbers,"_"); print numbers[1]}'`"_logs.txt"
    TIME=`echo $line | awk '{split($0,numbers,"_"); print numbers[2]}'`"[0-9]{2}"

    grep -iE ${TIME} ${TENT} >> ${FILE1}
done

我需要一个15秒保证金的解决方案,任何时间都不是60秒。我希望以格式filename_hh:mm:ss输入并输入hh:mm:ss +/- 15s或filename_hh:mm:ss(1)_hh:mm:ss(2)并采取行hh:mm:ss(1)和hh:mm:ss(2)之间的线。有时没有线路,所以解决方案应该认识到'如果有时匹配输入的间隔。

日志文件如下所示:

1002143 1002143 2014/15/05 22:09:52.937004 bla 
1002130         2014/15/05 22:09:44.786002 bla bla
1001667         2014/15/05 22:09:44.592009 bl a bla
1001667 1001667 2014/15/05 22:09:44.592009 bl a bla

5 个答案:

答案 0 :(得分:10)

我相信sed是最好的选择:

sed -rne '/<timestamp>/,/<timestamp>/ p' <file>

<强>例如:

tiago@dell:~$ sed -rne '/08:17:38/,/08:24:36/ p' /var/log/syslog 
May 16 08:17:38 dell AptDaemon.Worker: INFO: Processing transaction /org/debian/apt/transaction/08a244f7b8ce4fad9f6b304aca9eae7a
May 16 08:17:50 dell AptDaemon.Worker: INFO: Finished transaction /org/debian/apt/transaction/08a244f7b8ce4fad9f6b304aca9eae7a
May 16 08:18:50 dell AptDaemon.PackageKit: INFO: Initializing PackageKit transaction
May 16 08:18:50 dell AptDaemon.Worker: INFO: Simulating trans: /org/debian/apt/transaction/37c3ef54a6ba4933a561c49b3fac5f6e
May 16 08:18:50 dell AptDaemon.Worker: INFO: Processing transaction /org/debian/apt/transaction/37c3ef54a6ba4933a561c49b3fac5f6e
May 16 08:18:51 dell AptDaemon.PackageKit: INFO: Get updates()
May 16 08:18:52 dell AptDaemon.Worker: INFO: Finished transaction /org/debian/apt/transaction/37c3ef54a6ba4933a561c49b3fac5f6e
May 16 08:24:36 dell AptDaemon: INFO: Quitting due to inactivity

答案 1 :(得分:5)

日志文件通常按时间戳排序,假设时间戳在第一列,您可以:

awk -v from="12:52:33" -v to="12:59:33" '$1>=from && $1<=to' foo.log

通过这种方式,您可以更改from and to以获取不同的日志条目集。正则表达式不是进行数字计算/比较的好工具。

答案 2 :(得分:3)

您可以在egrep中使用此正则表达式:

egrep '12:5[2-9]:33' file.log

答案 3 :(得分:2)

您使用错误的工具执行此任务。一旦你有一个像@anubhava给出的正则表达式,你可以很容易地找到一个与之不匹配的时间间隔。 grep和正则表达式可能适用于一些特殊情况,但它们无法扩展到一般情况。

你能使用一些实际上能够理解的工具吗?时间戳?可能每种脚本语言(perl,python,ruby,lua)都有内置或库支持来解析时间和日期。

但是,您可以使用GNU日期的权力:

% date --date="2014-05-15 21:58:00 15 sec ago" +'%Y-%m-%d %H:%M:%S'
2014-05-15 21:57:45
% date --date="2014-05-15 21:58:00 15 sec" +'%Y-%m-%d %H:%M:%S' 
2014-05-15 21:58:15

并将其插入Tiago的sed过滤器中。

答案 4 :(得分:1)

您可以尝试以下perl脚本:

#! /usr/bin/perl

use warnings;
use strict;
use Time::Piece;
use autodie;

my $arg=shift;
my @a =split("_",$arg);
my $fn=shift @a;

my $dfmt='%Y/%d/%m';
my $fmt=$dfmt.' %H:%M:%S';
my $t = localtime;
my $date=$t->strftime($dfmt);
my $t1; my $t2;
if (@a == 1) {
   my $d=$date.' '.$a[0];
   my $tt=Time::Piece->strptime($d, $fmt);
   $t1=$tt-15;
   $t2=$tt+15;
} elsif (@a == 2) {
   $t1=Time::Piece->strptime($date.' '.$a[0], $fmt);
   $t2=Time::Piece->strptime($date.' '.$a[1], $fmt);
} else {
   die "Unexpected input argument!";
}

$fn=$fn.'_logs.txt';
doGrep($fn,$t1,$t2,$fmt);

sub doGrep { 
   my ($fn,$t1,$t2,$fmt) = @_;

   open (my $fh, "<", $fn);
   while (my $line=<$fh>) {
      my ($d1,$d2) = $line=~/\S+\s+(\S+)\s+(\d\d:\d\d:\d\d)/;
      my $d=$d1.' '.$d2;
      my $t=Time::Piece->strptime($d, $fmt);
      print $line if ($t>$t1 && $t<$t2);
   }
   close ($fh);
}

使用语法./p.pl A_22:09:14从命令行运行它。