SED在时间戳之间解析apache日志

时间:2018-04-25 04:21:27

标签: linux shell awk sed

我正在尝试解析日志并获取时间戳之间的界限。如下所示的方法,但面临正则表达式的问题

记录模式:

IP - - [20/Apr/2018:14:25:37 +0000] "GET / HTTP/1.1" 301 3936 "-" "
IP - - [20/Apr/2018:14:44:08 +0000]
----------------------------------

IP- - [20/Apr/2018:20:43:46 +0000]

由于日志中还包含其他日期,因此我需要在14:2520:43之间获取第4个月的行。

试过这个:

sed -n '/\[14:25/,/\[20:43/p' *-https_access.log.1

但没有工作。

4 个答案:

答案 0 :(得分:1)

由于你提到你想要4月20日的日志,我建议像:

$ sed -n '/20\/Apr\/2018:14:25/,/20\/Apr\/2018:20:43/p' *-https_access.log.1

如果“20:43”发生在其他地方,这种情况与错误匹配的可能性很小。

答案 1 :(得分:0)

要使用sed或awk打印match1match2之间的行,您可以执行以下操作:

sed -n '/match1/,/match2/p' inputfile
awk '/match1/,/match2/' inputfile
您的示例中的

match120/Apr/2018:14:25match220/Apr/2018:20:43。所以这些命令中的任何一个都适合你:

sed -n '/20\/Apr\/2018:14:25/,/20\/Apr\/2018:20:43/p' inputfile
awk '/20\/Apr\/2018:14:25/,/20\/Apr\/2018:20:43/' inputfile

或使用|作为sed的分隔符以防止转义斜杠:

sed -n '\|20/Apr/2018:14:25|,\|20/Apr/2018:20:43|p' inputfile

答案 2 :(得分:0)

sed不合适,因为它很难比较元素(如日和小时)。

用awk(自评):

awk -F '[ []' '
  {
  # separt date and hour then rebuild the fields
  sub(/:/, " ", $5);$0=$0""
  }

  # print if it s the day and between the 2 hour (string compare works in this case)
  $5 ~ /20.Apr.2018/ && $6 >= "04:25" &&  $7 < "20:44"
  ' YourFile

更常见的是,我们可以使用变量将日期和小时作为awk的参数(这里不是目的)

答案 3 :(得分:0)

最佳解决方案是使用awk。您需要做的是将时间戳转换为unix-time然后进行比较。在awk中,您可以使用mktime()

执行此操作
  

mktime(datespec [, utc-flag ]) :将datepec转换为与systime()返回的格式相同的时间戳。它类似于   ISO C中相同名称的函数。参数,datespec,是一个   YYYY MM DD HH MM SS [DST]形式的字符串。该字符串由   六个或七个数字分别代表全年   包括世纪,月份从1到12,月份从1   到了31,小时从0到23,分钟从0到59,   从0到60,55的秒数和可选的夏令时标志。

要将表单20/Apr/2018:14:25:37 +0000的时间格式转换为2018 04 20 14 25 37 +0000

awk -v tstart="20/Apr/2018:14:25:00" -v tend = "20/Apr/2018:20:43:00" \
     'function tounix(str) {
        split(str,a,"/|:| ")
        return mktime(a[3]" "month[a[2]]" "a[1]" "a[4]" "a[5]" "a[6])
     }
     BEGIN{
       month["Jan"]="01";month["Feb"]="02";month["Mar"]="03"
       month["Apr"]="04";month["May"]="05";month["Jun"]="06"
       month["Jul"]="07";month["Aug"]="08";month["Sep"]="09"
       month["Oct"]="10";month["Nov"]="11";month["Dec"]="12"
       FS="\\[|\\]"
       t1=tounix(tstart)
       t2=tounix(tend)
     }
     { t=tounix($2) }
     (t1<=t && t<=t)' <file>

这种方法非常稳健,因为它可以进行真正的时间比较,这与闰年,日/月/年交叉无关......,与提供的其他解决方案相比,此方法也不需要存在tstart

中的日期tendfile