Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何使用awk在所有频繁的时间间隔之间读取数据_Bash_Unix_Awk_Unix Timestamp - Fatal编程技术网

Bash 如何使用awk在所有频繁的时间间隔之间读取数据

Bash 如何使用awk在所有频繁的时间间隔之间读取数据,bash,unix,awk,unix-timestamp,Bash,Unix,Awk,Unix Timestamp,我的日志文件的格式如下 [30/Jan/2015:10:10:30 +0000] 12.30.30.204 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=- 200 425 [30/Jan/2015:10:11:00 +0000] 12.30.30.204 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=-

我的日志文件的格式如下

[30/Jan/2015:10:10:30 +0000] 12.30.30.204 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=- 200 425
[30/Jan/2015:10:11:00 +0000] 12.30.30.204 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=- 200 261
[30/Jan/2015:10:11:29 +0000] 12.30.30.204 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=- 200 232
[30/Jan/2015:10:12:00 +0000] 12.30.30.204 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=- 200 315
[30/Jan/2015:10:12:29 +0000] 12.30.30.204 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=- 200 221
[30/Jan/2015:10:12:57 +0000] 12.30.30.182 xff=- reqId=[-] status_check len=- GET /api/getstatus HTTP/1.1 mi=- ec=- 200 218
此日志文件中的每一行在第一个字段中有时间戳,在最后一个字段中有响应时间。在
awk
中是否有方法读取所有特定间隔内的平均响应时间?例如,根据日志文件中的时间戳,每五分钟计算一次平均响应时间

或者除了
awk
之外,还有什么更好的替代方法吗?请建议

更新:

我尝试了下面的方法,这是一种静态的方法,只给出一个时间间隔的平均值

$ grep "30/Jan/2015:10:1[0-4]" mylog.log | awk '{resp+=$NF;cnt++;}END{print "Avg:"int(resp/cnt)}'

但是我需要为整个文件做5分钟。即使循环该命令,如何将日期动态传递给该命令?因为日志文件每次都不同,其中的日期也不同。

嗯。GNU date不喜欢您的日期格式,所以我想我们必须自己解析它。我的思路是这样的(这需要对
mktime
进行呆呆的思考):

如果您确定日志文件将按升序排序(可能是这种情况),则可以通过替换

curtime >= start && curtime < end {
  sum += $NF
  ++count
}
在找到第一个位于您要查找的范围之后,这将停止搜索拟合日志条目

附录:由于OP澄清了他希望在一个排序的makefile中对所有五分钟的间隔进行总结,因此需要一个经过调整的脚本来实现这一点

#!/usr/bin/awk -f

function parse_timestamp(stamp) {
  split(stamp, c, "[][/: ]")
  return mktime(c[4] " " mnums[c[3]] " " c[2] " " c[5] " " c[6] " " c[7])
}

BEGIN {
  split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", mnames)
  for(i = 1; i <= length(mnames); ++i) {
    mnums[mnames[i]] = i
  }
}

{ 
  curtime = parse_timestamp($1)
}

NR == 1 {
  # pull the start time from the first line
  start = curtime
  end   = start + 300
}

curtime > end {
  # print result, reset counters when endtimes are past
  print "Avg: " (count == 0 ? "undef" : sum / count)
  sum   = 0
  count = 0
  end  += 300
}

{
  sum += $NF
  ++count
}

END {
  # print once more at the very end for the last, unfinished interval.
  print "Avg: " (count == 0 ? "undef" : sum / count)
}
#/usr/bin/awk-f
函数解析_时间戳(stamp){
拆分(盖章,c,“[]/:]”)
返回mktime(c[4]“”mnums[c[3]“”c[2]“”c[5]“”c[6]“”c[7])
}
开始{
拆分(“1-2-3-4-5-6-7-8-9-10-11-12”,mnames)
对于(i=1;i结束){
#打印结果,结束时间过去时重置计数器
打印“平均值:”(计数=0?“未定义”:总和/计数)
总和=0
计数=0
完+=300
}
{
总和+=$NF
++计数
}
结束{
#在最后一个未完成的间隔的末尾再次打印。
打印“平均值:”(计数=0?“未定义”:总和/计数)
}

嗯。GNU date不喜欢您的日期格式,所以我想我们必须自己解析它。我的思路是这样的(这需要对
mktime
进行检查):

如果您确定日志文件将按升序排序(可能是这种情况),则可以通过替换

curtime >= start && curtime < end {
  sum += $NF
  ++count
}
在找到第一个位于您要查找的范围之后,这将停止搜索拟合日志条目

附录:由于OP澄清了他希望在一个排序的makefile中对所有五分钟的间隔进行总结,因此需要一个经过调整的脚本来实现这一点

#!/usr/bin/awk -f

function parse_timestamp(stamp) {
  split(stamp, c, "[][/: ]")
  return mktime(c[4] " " mnums[c[3]] " " c[2] " " c[5] " " c[6] " " c[7])
}

BEGIN {
  split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", mnames)
  for(i = 1; i <= length(mnames); ++i) {
    mnums[mnames[i]] = i
  }
}

{ 
  curtime = parse_timestamp($1)
}

NR == 1 {
  # pull the start time from the first line
  start = curtime
  end   = start + 300
}

curtime > end {
  # print result, reset counters when endtimes are past
  print "Avg: " (count == 0 ? "undef" : sum / count)
  sum   = 0
  count = 0
  end  += 300
}

{
  sum += $NF
  ++count
}

END {
  # print once more at the very end for the last, unfinished interval.
  print "Avg: " (count == 0 ? "undef" : sum / count)
}
!/usr/bin/awk-f
函数解析_时间戳(stamp){
拆分(盖章,c,“[]/:]”)
返回mktime(c[4]“”mnums[c[3]“”c[2]“”c[5]“”c[6]“”c[7])
}
开始{
拆分(“1-2-3-4-5-6-7-8-9-10-11-12”,mnames)
对于(i=1;i结束){
#打印结果,结束时间过去时重置计数器
打印“平均值:”(计数=0?“未定义”:总和/计数)
总和=0
计数=0
完+=300
}
{
总和+=$NF
++计数
}
结束{
#在最后一个未完成的间隔的末尾再次打印。
打印“平均值:”(计数=0?“未定义”:总和/计数)
}

嗯。GNU date不喜欢您的日期格式,所以我想我们必须自己解析它。我的思路是这样的(这需要对
mktime
进行检查):

如果您确定日志文件将按升序排序(可能是这种情况),则可以通过替换

curtime >= start && curtime < end {
  sum += $NF
  ++count
}
在找到第一个位于您要查找的范围之后,这将停止搜索拟合日志条目

附录:由于OP澄清了他希望在一个排序的makefile中对所有五分钟的间隔进行总结,因此需要一个经过调整的脚本来实现这一点

#!/usr/bin/awk -f

function parse_timestamp(stamp) {
  split(stamp, c, "[][/: ]")
  return mktime(c[4] " " mnums[c[3]] " " c[2] " " c[5] " " c[6] " " c[7])
}

BEGIN {
  split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", mnames)
  for(i = 1; i <= length(mnames); ++i) {
    mnums[mnames[i]] = i
  }
}

{ 
  curtime = parse_timestamp($1)
}

NR == 1 {
  # pull the start time from the first line
  start = curtime
  end   = start + 300
}

curtime > end {
  # print result, reset counters when endtimes are past
  print "Avg: " (count == 0 ? "undef" : sum / count)
  sum   = 0
  count = 0
  end  += 300
}

{
  sum += $NF
  ++count
}

END {
  # print once more at the very end for the last, unfinished interval.
  print "Avg: " (count == 0 ? "undef" : sum / count)
}
!/usr/bin/awk-f
函数解析_时间戳(stamp){
拆分(盖章,c,“[]/:]”)
返回mktime(c[4]“”mnums[c[3]“”c[2]“”c[5]“”c[6]“”c[7])
}
开始{
拆分(“1-2-3-4-5-6-7-8-9-10-11-12”,mnames)
对于(i=1;i结束){
#打印结果,结束时间过去时重置计数器
打印“平均值:”(计数=0?“未定义”:总和/计数)
总和=0
计数=0
完+=300
}
{
总和+=$NF
++计数
}
结束{
#在最后一个未完成的间隔的末尾再次打印。
打印“平均值:”(计数=0?“未定义”:总和/计数)
}

嗯。GNU date不喜欢您的日期格式,所以我想我们必须自己解析它。我的思路是这样的(这需要对
mktime
进行检查):

如果您确定日志文件将按升序排序(可能是这种情况),则可以通过替换

curtime >= start && curtime < end {
  sum += $NF
  ++count
}
在找到第一个位于您要查找的范围之后,这将停止搜索拟合日志条目

附录:由于OP澄清了他希望在一个排序的makefile中对所有五分钟的间隔进行总结,因此需要一个经过调整的脚本来实现这一点

#!/usr/bin/awk -f

function parse_timestamp(stamp) {
  split(stamp, c, "[][/: ]")
  return mktime(c[4] " " mnums[c[3]] " " c[2] " " c[5] " " c[6] " " c[7])
}

BEGIN {
  split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", mnames)
  for(i = 1; i <= length(mnames); ++i) {
    mnums[mnames[i]] = i
  }
}

{ 
  curtime = parse_timestamp($1)
}

NR == 1 {
  # pull the start time from the first line
  start = curtime
  end   = start + 300
}

curtime > end {
  # print result, reset counters when endtimes are past
  print "Avg: " (count == 0 ? "undef" : sum / count)
  sum   = 0
  count = 0
  end  += 300
}

{
  sum += $NF
  ++count
}

END {
  # print once more at the very end for the last, unfinished interval.
  print "Avg: " (count == 0 ? "undef" : sum / count)
}
!/usr/bin/awk-f
函数解析_时间戳(stamp){
拆分(盖章,c,“[]/:]”)
返回mktime(c[4]“”mnums[c[3]“”c[2]“”c[5]“”c[6]“”c[7])
}
开始{
拆分(“1-2-3-4-5-6-7-8-9-10-11-12”,mnames)
对于(i=1;i结束){
#打印结果,结束时间过去时重置计数器
打印“平均值:”(计数=0?“未定义”:总和/计数)
总和=0
计数=0
完+=300
}
{
总和+=$NF
++计数
}
结束{
#在最后一个未完成的间隔的末尾再次打印。
打印“平均值:”(计数=0?“未定义”:总和/计数)
}

@Jotne。添加到问题中。请看一看。如果您正在使用awk,您永远不需要grep,因为awk可以做grep可以做的任何有用的事情do@EdMorton,是的,我知道这一点,但我在尝试此操作时找不到awk时间戳解析脚本,所以最初尝试使用grep。您只需要避开反斜杠,因为这是awk regexp delimiter
grep“30/Jan/2015:10:1[0-4]”mylog.log | awk'{foo}
->
awk'/30\/Jan\/2015:10:1[0-4]/