【问题标题】:awk subtract value found with first and last line of a logawk 减去在日志的第一行和最后一行找到的值
【发布时间】:2022-01-15 21:38:14
【问题描述】:

我正在尝试查找操作的总持续时间。 在日志中,我想检索包含元素(如文件)的特定对象名称(比如说文件夹)列表的删除操作的每一行。 日志会报告每个删除操作:为了测量特定对象的删除持续时间,我可以将第一个删除的时间戳减去最后一个删除的时间戳。

我找到了一种执行此操作的方法,但我想听听您的建议,以使其外观和性能更好。

for name in $(cat List_to_Del) ; do
    grep $name access_log |
    grep "method=DELETE" |
    awk 'NR==1 ; END{print}' |
    awk -F, '{print $3}' |
    awk -F= '{print $2}' |
    paste -sd- - |
    bc |
    awk -F- '{print $NF}'
done

For 循环。我正在查看已删除名称的列表并在我的日志中搜索它们。 我按名称检索 DELETE 操作的完整列表。 然后(第一个 awk 命令)我只保留每个名称的第一行和最后一行。 然后我只检索字段编号 3 中的字段编号 2。 然后我使用粘贴命令将两个值写入一行,并以符号“-”作为分隔符,将其推送到 bc 并删除减号。

这是一个日志示例:

16/Nov/2021:17:07:42,100,ts=1637078862.235,method=DELETE,name1,,,
16/Nov/2021:17:07:42,100,ts=1637078862.236,method=PUT,name4,,,
16/Nov/2021:17:07:42,100,ts=1637078862.243,method=DELETE,name1,,,
16/Nov/2021:17:07:42,100,ts=1637078862.254,method=DELETE,name2,,,
16/Nov/2021:17:07:42,100,ts=1637078862.256,method=DELETE,name1,,,
16/Nov/2021:17:07:42,100,ts=1637078862.260,method=DELETE,name2,,,

【问题讨论】:

  • 请参阅stackoverflow.com/help/formatting 了解如何格式化您的代码、输入和输出块,然后查看edit 修复它们的问题(将它们全部格式化为“代码块”)。另外,不要将所有代码都塞到一行中,因为这只会让我们更难阅读。
  • 我刚刚为你做了,所以你可以在下一个问题中看到如何做。
  • edit您的问题提供您提供的示例输入的预期输出。

标签: awk


【解决方案1】:

我会为此使用 GNU AWK,让 file.txt 内容成为

16/Nov/2021:17:07:42,100,ts=1637078862.235,method=DELETE,name1,,,
16/Nov/2021:17:07:42,100,ts=1637078862.236,method=PUT,name4,,,
16/Nov/2021:17:07:42,100,ts=1637078862.243,method=DELETE,name1,,,
16/Nov/2021:17:07:42,100,ts=1637078862.254,method=DELETE,name2,,,
16/Nov/2021:17:07:42,100,ts=1637078862.256,method=DELETE,name1,,,
16/Nov/2021:17:07:42,100,ts=1637078862.260,method=DELETE,name2,,,

然后

awk 'BEGIN{FS=",|="}/method=DELETE/{if(flag){finish=$4}else{start=$4;flag=1}}END{print finish-start}' file.txt

输出

0.0250001

解释:我通知 GNU AWK 字段分隔符 (FS) 是 , 或 (|) =,因此 ts 值将进入第 4 列(第一个:日期时间,第二个:秒数百,第 3:文字 ts)。对于带有method=DELETE 的每一行,如果设置了flag,我将finish 变量值设置为ts 值,如果尚未设置flag,那么我将start 变量值设置为ts 值。最后(在END)我printfinishstart之间的区别。

(在 GNU Awk 5.0.1 中测试)

【讨论】:

  • 您知道您可以在代码中添加一些空格。
  • @glennjackman 但是任何人都可以阅读它...... :-)。
【解决方案2】:

这是你想要做的吗?

$ cat tst.awk
BEGIN { FS="," }
$4 == "method=DELETE" {
    name = $5
    time = $3
    sub(/.*=/,"",time)
    end[name] = time

    if ( !(name in beg) ) {
        beg[name] = time
    }
}
END {
    for (name in beg) {
        print name, end[name] - beg[name]
    }
}

$ awk -f tst.awk access_log
name1 0.0210001
name2 0.00600004

如果您真的只想分析日志中名称的目标子集,那么它会是:

$ cat List_to_Del
name2

$ cat tst.awk
BEGIN { FS="," }
NR==FNR {
    tgts[$0]
    next
}
{ name = $5 }
(name in tgts) && ($4 == "method=DELETE") {
    time = $3
    sub(/.*=/,"",time)
    end[name] = time

    if ( !(name in beg) ) {
        beg[name] = time
    }
}
END {
    for (name in beg) {
        print name, end[name] - beg[name]
    }
}

$ awk -f tst.awk List_to_Del access_log
name2 0.00600004

【讨论】:

    【解决方案3】:

    通过一次通过日志文件,您可以收集所有名称的“last - first”

    awk -F'[,=]' '
        $6 != "DELETE" {next}
        !($7 in first) {first[$7] = $4}
        {last[$7] = $4}
        END {for (name in first) print name, last[name] - first[name]}
    ' log
    
    name1 0.0210001
    name2 0.00600004
    

    然后,您可以使用 List_to_Del 和一个 grep 过滤掉您想要/不想要的那些

    $ cat List_to_Del
    name1
    
    $ awk -F'[,=]' '
          $6 != "DELETE" {next}
          !($7 in first) {first[$7] = $4}
          {last[$7] = $4}
          END {
              for (name in first)
                  print name, last[name] - first[name]
          }
      ' log | grep -v -w -F -f List_to_Del
    name2 0.00600004
    

    如果该过滤器输出向后,请删除-v

    【讨论】:

      猜你喜欢
      • 2016-05-23
      • 1970-01-01
      • 2018-03-07
      • 2019-07-24
      • 2022-10-25
      • 1970-01-01
      • 2019-11-04
      • 2012-02-16
      • 1970-01-01
      相关资源
      最近更新 更多