在AWK中运行shell命令

时间:2011-05-03 20:58:33

标签: shell unix awk

我正在尝试处理日志文件,我需要能够指定日期范围。到目前为止(在任何处理之前),我正在使用date --date "monday" +%s将日期/时间字符串转换为时间戳。

现在,我希望能够迭代文件中的每一行,但检查日期(以人类可读的格式)是否在允许的范围内。为此,我想做类似以下的事情:

echo `awk '{if(`date --date "$3 $4 $5 $6 $7" +%s` > $START && `date --date "" +%s` <= $END){/*processing code here*/}}' myfile`

我甚至不知道那是否可能......我尝试了很多变化,而且我找不到任何可理解/可用的在线。

由于

更新

myfile示例如下。其记录IP和访问时间:

123.80.114.20      Sun May 01 11:52:28 GMT 2011
144.124.67.139     Sun May 01 16:11:31 GMT 2011
178.221.138.12     Mon May 02 08:59:23 GMT 2011

3 个答案:

答案 0 :(得分:1)

鉴于你必须做什么,它真的不那么难,通过转换为字符串和比较来进行日期处理会更有效率。

这是使用关联数组将月份值转换为数字的部分解决方案。然后依靠%02d格式说明符来确保2位数。您可以使用“。”等重新格式化dateTime值,或者如果您确实需要人类可读性,则将冒号保留在hr:min:sec中。

YYYYMMDD格式对这类问题有很大帮助,因为LT,GT,EQ都可以正常工作而无需进一步格式化。

echo "178.221.138.12     Mon May 02 08:59:23 GMT 2011" \
| awk 'BEGIN {
mons["Jan"]=1 ; mons["Feb"]=2; mons["Mar"]=3
mons["Apr"]=4 ; mons["May"]=5; mons["Jun"]=6
mons["Jul"]=7 ; mons["Aug"]=8; mons["Sep"]=9
mons["Oct"]=10 ; mons["Nov"]=11; mons["Dec"]=12
}
{ 
   # 178.221.138.12     Mon May 02 08:59:23 GMT 2011
   printf("dateTime=%04d%02d%02d%02d%02d%02d\n", 
       $NF, mons[$3], $4, substr($5,1,2), substr($5,4,2), substr($5,7,2) )
} ' -v StartTime=20110105235959

-v StartTime是关于如何传入(及匹配格式)starTime值的说明。

我希望这会有所帮助。

答案 1 :(得分:1)

这是使用awk的内置mktime()函数的替代方法。到目前为止,我从未对解析月份感到困扰 - 感谢那个部分的庇护所(见接受的答案)。在这一点上转换语言总是感觉时间。

#!/bin/bash
# input format:
#(1                  2   3   4  5        6   7)
#123.80.114.20      Sun May 01 11:52:28 GMT 2011

awk -v startTime=1304252691 -v endTime=1306000000 '
BEGIN {
  mons["Jan"]=1 ; mons["Feb"]=2; mons["Mar"]=3
  mons["Apr"]=4 ; mons["May"]=5; mons["Jun"]=6
  mons["Jul"]=7 ; mons["Aug"]=8; mons["Sep"]=9
  mons["Oct"]=10 ; mons["Nov"]=11; mons["Dec"]=12;
}
{
  hmsSpaced=$5; gsub(":"," ",hmsSpaced); 
  timeInSec=mktime($7" "mons[$3]" "$4" "hmsSpaced); 
  if (timeInSec > startTime && timeInSec <= endTime) print $0
}' myfile

(我选择了示例时间阈值来仅选择最后两个日志行。)

请注意,如果mktime()函数更聪明一点,那么整个事情将减少为:

awk -v startTime=1304252691 -v endTime=1306000000 't=mktime($7" "$3" "$4" "$5); if (t > startTime && t <= endTime) print $0}' myfile

答案 2 :(得分:0)

我不确定您正在解析的数据的格式,但我知道您不能在单引号内使用反引号。你必须使用双引号。如果嵌套的引号太多,并且让您感到困惑,您也可以事先将date命令的输出保存到变量中。