构建逻辑 - 还有什么比使用 AWK 更好的呢?

构建逻辑 - 还有什么比使用 AWK 更好的呢?

下面是日志的样子:

Company=XYZ
Req_id=1234
Time_taken=10 sec
Status=Success

Company=ABC
Req_id=3456
Time_taken=200 sec
Status=Failure

Company=DFG
Req_id=3001
Time_taken=15 sec
Status=Success

我们必须获取花费最长时间的前 3 个请求 ID。

我尝试使用以下解决方案,获取请求 ID 和所用时间,但我对我的答案不满意:

awk -vRS= -F'[=\n]' '/Time_taken/{print $4,$6}' test.txt | sort -nr

我怎样才能做得更好呢?使用一些逻辑来编码而不是内置函数。另外,我需要-F'[=\n]'更好地理解吗?我只是从以前的脚本中复制它。

输出应该是:

Below Request Id took more then expected
Request id 3456, Time Taken 200 sec
Request id 3001, Time Taken 15 sec  
Request id 1234, Time Taken 10 sec

答案1

仅使用awk

function list_insert (value, id, tmp) {
    for (i = 1; i <= list_length; ++i)
        if (value > value_list[i]) {
            tmp = value_list[i]
            value_list[i] = value
            value = tmp

            tmp = id_list[i]
            id_list[i] = id
            id = tmp
        }
}

BEGIN {
    FS = "[= ]"
    list_length = 3
}

$1 == "Req_id"     { id = $2 }
$1 == "Time_taken" { list_insert($2, id) }

END {
    printf("Below Request Id took more then expected\n")
    for (i = 1; i <= list_length; ++i)
        printf("Request id %d, time taken %d sec\n", id_list[i], value_list[i])
}

该程序维护两个数组value_listid_list,长度均为list_length。该value_list数组已排序并包含时间值,而该id_list数组包含与第一个列表中的值相对应的请求 ID。

list_insert函数将新值和 ID 插入到两个数组中,并保持数组的顺序value_list(它找到正确的插入位置,然后将剩余的项目打乱到末尾)。

程序的其余部分将数据读取为由=或 空格分隔的字段的换行分隔记录。当找到请求 ID 时,会将其保存在 中id,而当找到“所用时间”条目时,该 ID 和所用时间值将被插入到数组中。

最后,这两个数组用于创建输出。

测试它:

$ awk -f script.awk file
Below Request Id took more then expected
Request id 3456, time taken 200 sec
Request id 3001, time taken 15 sec
Request id 1234, time taken 10 sec

答案2

我们可以使用段落模式来做到这一点,Perl其中我们读取段落大小的文件块作为记录,并随着时间的推移建立一个以 ID 和值为键的哈希值。在文件末尾,我们对所用时间进行数字反向排序,然后打印所需的消息。

$ perl -ln -00 -e '
    %h = (%h, /^Req_id=(\d+)\n.*^Time_taken=(\d+)/ms)}{
    print "The below IDs took more than expected:" if scalar keys %h;
    print join " ", "Req ID:", "$_," , "Time taken", $h{$_}, "sec"
       for (sort { $h{$b} <=> $h{$a}  } keys %h)[0..2];
' input.file

输出:

The below IDs took more than expected:
Req ID: 3456, Time taken 200 sec
Req ID: 3001, Time taken 15 sec
Req ID: 1234, Time taken 10 sec

答案3

您需要记住请求号。

我会用(这可能是一排)

awk -F= '$1 == "Req_id" {r=$2 ; } 
   $1 == "Time_taken" { printf "Request id %s %s %s\n",r,$1,$2 ; }' file |
sort -r -n -k5 |
head -3

这给了

Request id 3456 Time_taken 200 sec
Request id 3001 Time_taken 15 sec
Request id 1234 Time_taken 10 sec

在哪里

  • -F=用作=分隔符
  • $1 == "Req_id" {r=$2 ; }获取最后一个请求id
  • $1 == "Time_taken"如果该行是“花费时间”
  • { printf "Request id %s %s %s\n",r,$1,$2 ; }打印请求 ID 和秒数
  • | sort管道排序
  • -r相反的顺序
  • -n数字排序(例如 200 大于 15)
  • -k5在5号场
  • | head -3获取前 3 行

答案4

除了单行代码之外,我更喜欢 Python 而不是 awk。使用 Python 脚本可以让您更轻松地处理格式不良的输入并执行日志记录和错误处理。

这是一个基本的 Python 脚本,它将为您的示例输入生成所需的输出,并且它的结构暗示您如何在需要时进一步构建它:

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""parse_log.py"""

import sys
from collections import OrderedDict

logfilepath = sys.argv[1]

# Define a function to parse a single block/entry in the log file
def parse_block(block):
    parsed_block = dict()
    lines = block.split("\n")
    for line in lines:
        if line.startswith("Company="):
            parsed_block["Company"] = line[8:]
        elif line.startswith("Req_id="):
            parsed_block["Required_ID"] = line[7:]
        elif line.startswith("Time_taken="):
            parsed_block["Time_Taken"] = line[11:]
        elif line.startswith("Status="):
            parsed_block["Status"] = line[7:]
        else:
            pass
    return parsed_block

# Initialize a list to store the processed entries
parsed_blocks = list()

# Populate the list
with open(logfilepath, "r") as logfile:
    blocks = logfile.read().split("\n\n")
    for block in blocks:
        parsed_block = parse_block(block)
        parsed_blocks.append(parsed_block)

# Print the results
print("Below Request Id took more then expected")
for parsed_block in parsed_blocks:
    print("Request id {}, Time Taken: {}".format(parsed_block["Required_ID"], parsed_block["Time_Taken"]))

你可以这样运行它:

python parse_log.py data.log

在您的示例输入中,它会生成以下输出(根据要求):

Below Request Id took more then expected
Request id 1234, Time Taken: 10 sec
Request id 3456, Time Taken: 200 sec
Request id 3001, Time Taken: 15 sec

相关内容