linux - 使用awk解析转换如下日志

标签 linux awk

我有一个这样的日志:

DEBUG: Worker thread (#12) initialized
DEBUG: Worker thread (#19) initialized
DEBUG: Worker thread (#9) initialized
DEBUG: Worker thread (#15) initialized
DEBUG: Worker thread (#3) initialized
DEBUG: Worker thread (#17) initialized
DEBUG: Worker thread (#14) initialized
DEBUG: Worker thread (#16) initialized
Threads started!

[ 5s ] thds: 20 tps: 35265.85 qps: 35265.85 (r/w/o: 0.00/35265.85/0.00) lat (ms,99%): 2.52 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 20 tps: 35965.67 qps: 35965.67 (r/w/o: 0.00/35965.67/0.00) lat (ms,99%): 2.03 err/s: 0.00 reconn/s: 0.00
...

我想解析这个日志文件并获取以下所有行:

[ 5s ] thds: 20 tps: 35265.85 qps: 35265.85 (r/w/o: 0.00/35265.85/0.00) lat (ms,99%): 2.52 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 20 tps: 35965.67 qps: 35965.67 (r/w/o: 0.00/35965.67/0.00) lat (ms,99%): 2.03 err/s: 0.00 reconn/s: 0.00
....

然后我想将这些线条转换成以下格式进行绘图:

5,35265.85
10,35965.67
...

这是我的 awk 代码:

#!/usr/bin/env bash
awk '
BEGIN {
printf "#time,tps\n";
}
/^\[\ [0-9]{1,4}[s]?\ \]/ { # regex for [ 1050s ]
printf "%s,%s\n", substr($2,1, length($2)-1), $7
}
' "$@"

我不喜欢这个解决方案的一点是:我必须手动计算 awk 生成的标记索引。我更喜欢更好的解决方案,例如:“字符串“tps”之后的第一个标记”。这样,它会更通用,更容易解析。

我的问题是:我真的可以使用 awk 来做到这一点吗?还是有更好的解决方案来处理我的情况?

最佳答案

这是执行此操作的一种方法。假设您的日志文件名为 data.txt .您可以运行以下命令

cat data.txt | grep -wE "5s|10s" | awk '{print substr($(NF-16), 1, length($(NF-16))-1) "," $(NF-13) "," $(NF-11) "," $(NF-9)}' 

说明

  1. cat <filename>将文件内容打印到标准输出
  2. grep -wE <exp>过滤 cat 的输出并选择包含表达式的行,在我们的例子中是 5s or 10s . -w确保只选择与整个单词匹配的行或 5s没有-w也选择15s, 20s ..等等,

这将选择以下行 awk正在运行

[ 5s ] thds: 20 tps: 35265.85 qps: 35265.85 (r/w/o: 0.00/35265.85/0.00) lat (ms,99%): 2.52 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 20 tps: 35965.67 qps: 35965.67 (r/w/o: 0.00/35965.67/0.00) lat (ms,99%): 2.03 err/s: 0.00 reconn/s: 0.00
  1. 使用 awk我们可以使用 NF找出每行中的字段数 awk '{print NF}'即 18

提取相应的内容在NF-16 , NF-13 , NF-11NF-9第 位置。即分别为第 2、5、7 和 9 位。但是,第二个位置是 5s|10s等等,你想删除尾部 s这可以通过 substr($2, 1, length($2)-1) 来完成即从第一个字符到 5s/10s 的长度,即相应的 2/3 并使用 -1 删除最后一个字符.

你的最终命令是

awk '{print substr($(NF-16), 1, length($(NF-16))-1) "," $(NF-13) "," $(NF-11) "," $(NF-9)}'

可以替换为

awk '{print substr($2, 1, length($2)-1)","$5","$7","$9}'

把所有的东西放在一起

cat data.txt | grep -wE "5s|10s" | awk '{print substr($2, 1, length($2)-1)","$5","$7","$9}'

关于linux - 使用awk解析转换如下日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56928584/

相关文章:

c - linux -c - 尽快从用户空间通知内核,反之亦然

linux - 如何以毫秒为单位获取 2 个日期(Z 格式)之间的差异

linux - 在颠覆中设置分支的问题

sed - 从另一个文件中的文本文件中删除行

Bash while read line 循环不打印条件中的每一行

linux - 为什么 `pw_gecos` 是这样命名的?

linux - 如何更改 Linux 中的组所有权?

linux - PowerShell 脚本查找文件中的特定单词并在行开头添加 “4”

bash - 使用 printf 格式化输出 : truncating or padding

bash - 在 AWK 中比较工程编号时出现奇怪的输出