从 UNIX 上的巨大日志文件中获取信息的快速方法

从 UNIX 上的巨大日志文件中获取信息的快速方法

我有一个 6 GB 的应用程序日志文件。日志具有以下格式(缩短)

[...]
timestamp;hostname;sessionid-ABC;type=m
timestamp;hostname;sessionid-ABC;set_to_TRUE
[...]
timestamp;hostname;sessionid-HHH;type=m
timestamp;hostname;sessionid-HHH;set_to_FALSE
[...]
timestamp;hostname;sessionid-ZZZ;type=m
timestamp;hostname;sessionid-ZZZ;set_to_FALSE
[...]
timestamp;hostname;sessionid-WWW;type=s
timestamp;hostname;sessionid-WWW;set_to_TRUE

除了这两行之外,我还有很多会议。我需要找出与type=m和相关的所有会话set_to_TRUE

我的第一次尝试是 grep 所有 sessionIDtype=m并将其写入文件中。然后通过大日志文件和 grep 循环文件中的每一行(每行 1 个 sessionID)sessionID;set_to_TRUE

这种方法需要花费大量时间。谁能给我一个提示,以更好更快的方式解决这个问题?

答案1

如果每个会话都有一个对应的typeand 是set_to或者TRUEFALSE那么您可以使用sedand 范围来执行此操作:

sed '/type=m/,/set_to_/!d;/set_to_TRUE$/!d;s/.*\(sessionid-.*\);.*/\1/' infile

这将删除不在/type=m/,/set_to_/范围内的所有行。它还删除那些范围内不以 结尾的行set_to_TRUEsessionid然后从剩余行(如果有)中提取。
或者,

sed -n '/type=/h;/set_to_TRUE$/{
x;s/.*\(sessionid-.*\);type=m$/\1/p
}' infile

应该打印相同的。
后者的工作原理是在每条匹配的行上覆盖保持缓冲区type=
然后,在每条匹配的行上set_to_TRUE,交换缓冲区并尝试替换 - 即sessionid从以 结尾的行中提取type=m- 如果成功,则打印结果p。否则,由于通过 禁用自动打印,因此不会发生任何事情-n
上面假设您的行中没有尾随空格。

答案2

使用这个awk命令:

awk -F";" '/type=m/{flag=$3;next} /set_to_TRUE/ && ($3==flag)' infile.txt

如果两个 sessionID 相同且所需条件也相同,则它将匹配。

timestamp;hostname;sessionid-ABC;set_to_TRUE

上面将打印整行,您可以通过添加来仅打印所需的列,print $3以便只有 sessionID,如下所示:

awk -F";" '/type=m/{flag=$3;next} /set_to_TRUE/ && ($3==flag){print $3}' infile.txt

答案3

使用 grep 可以很容易地完成:

grep -E "(type=|set_to_)" file.txt | grep -A 1 "type=m" | grep -B 1 "set_to_TRUE" > file1.txt &

把它放在后台,喝杯咖啡,让它完成。不确定“awk”或“sed”是否会更快。6GB 对于纯文本来说太多了,这就是为什么无论如何尝试这样做都会花费很长时间。

无论如何,一旦您按 Enter 或输入另一个命令,您就会在控制台中看到它何时完成:

[1]+  Done                    grep --color=auto -E '(type=|set_to_)' file.txt | grep --color=auto -A 1 "type=m" | grep --color=auto -B 1 "set_to_TRUE" > file1.txt

答案4

awk -F';' '/type=m/ { seen[$3]=1 };
           /set_to_TRUE/ && seen[$3] { print $3 ; delete seen[$3] };
           /set_to_FALSE/ && seen[$3] { delete seen[$3] }' logfile.txt

这类似于αГsнιn 的回答,但它不是仅使用单个变量 ( flag),而是使用数组 ( seen) 来跟踪它看到的匹配的会话 ID type=m

type=m这意味着,即使在任何会话的线路的瞄准type=m和该会话的线路的瞄准之间存在不同会话的其他线路,它也可以工作set_to_

为了最大限度地减少脚本的内存需求,它会在看到匹配的或seen时立即删除给定会话 ID 的数组元素。set_to_TRUEset_to_FALSE

注意:上面的脚本仅打印匹配的会话 ID。如果你想打印实际的type=mset_to_TRUE行,awk 脚本将是:

awk -F';' '/type=m/ { seen[$3]=$0 };
           /set_to_TRUE/ && seen[$3] { print seen[$3]"\n"$0 ; delete seen[$3] };
           /set_to_FALSE/ && seen[$3] { delete seen[$3] }' logfile.txt

这有可能使用更多的内存。将整个输入行存储在数组中比存储整数需要更多的 RAM。

注意 2:此脚本假定会话 ID 是唯一的。例如,如果不同的主机名(字段 2)可能生成相同的会话 ID,请尝试以下操作:

awk -F';' '/type=m/ { seen[$3$2]=1 };
           /set_to_TRUE/ && seen[$3$2] { print $3 ; delete seen[$3$2] };
           /set_to_FALSE/ && seen[$3$2] { delete seen[$3$2] }' logfile.txt

或者

awk -F';' '/type=m/ { seen[$3$2]=$0 };
           /set_to_TRUE/ && seen[$3$2] {print seen[$3$2]"\n"$0;delete seen[$3$2]};
           /set_to_FALSE/ && seen[$3$2] { delete seen[$3$2] }' logfile.txt

相关内容