我的答案将不基于 Java,因为这是一个可以以更简单的方式解决的问题的经典示例。
您只需要工具grep。如果你在 Windows 上,你可以找到它here。
假设您的日志在文件log.txt 中,您的问题的解决方案是一个单一的:
grep -hE --before-context 1 "^DB2[0-9]+E" log.txt > filtered.txt
解释:
-
-h - 不打印文件名
-
-E - 正则表达式搜索
-
--before-context 1 - 这将在找到错误消息之前打印一行(如果您的所有 SQL 查询都在一行中,这将起作用)
-
^DB2[0-9]+E - 搜索以“DB2”开头、包含一些数字并以“E”结尾的行
上面的表达式将在一个名为 filtered.txt 的新文件中打印您需要的每一行。
更新:经过一番摸索,我设法仅使用标准的 *nix 实用程序来获得所需的内容。小心,它不漂亮。最后的表达式:
grep -nE "^DB2[0-9]+" log.txt | cut -f 1 -d " " | gawk "/E$/{y=$0;print x, y};{x=$0}" | sed -e "s/:DB2[[:digit:]]\+[IE]//g" | gawk "{print \"sed -n \\\"\" $1+1 \",\" $2 \"p\\\" log.txt \"}" | sed -e "s/$/ >> filtered.txt/g" > run.bat
解释:
-
grep -nE "^DB2[0-9]+" log.txt - 打印以DB2... 开头的行及其开头的行号。示例:
6:DB20000I SQL 命令成功完成。
12:DB21034E 该命令被作为 SQL 语句处理,因为它不是有效的命令行处理器命令。
19:DB21034E 该命令被作为 SQL 语句处理,因为它不是有效的命令行处理器命令。
26:DB21034E 该命令被作为 SQL 语句处理,因为它不是有效的命令行处理器命令。
34:DB20000I SQL 命令成功完成。
41:DB20000I SQL 命令成功完成。
47:DB21034E 该命令作为 SQL 语句处理,因为它不是有效的命令行处理器命令。
54:DB20000I SQL 命令成功完成。
-
cut -f 1 -d " " - 仅打印“第一列”,即删除错误消息后的所有内容。示例:
6:DB20000I
12:DB21034E
19:DB21034E
26:DB21034E
34:DB20000I
41:DB20000I
47:DB21034E
54:DB20000I
-
gawk "/E$/{y=$0;print x, y};{x=$0}" - 对于以“E”结尾的每一行(错误行),打印它之前的行,然后是错误行。示例:
6:DB20000I 12:DB21034E
12:DB21034E 19:DB21034E
19:DB21034E 26:DB21034E
41:DB20000I 47:DB21034E
-
sed -e "s/:DB2[[:digit:]]\+[IE]//g" - 删除冒号和错误信息,只留下行号。示例:
6 12
12 19
19 26
41 47
-
gawk "{print \"sed -n \\\"\" $1+1 \",\" $2 \"p\\\" log.txt \"}" - 格式化以上行以进行 sed 处理并将第一行号加一。示例:
sed -n "7,12p" log.txt
sed -n "13,19p" log.txt
sed -n "20,26p" log.txt
sed -n "42,47p" log.txt
-
sed -e "s/$/ >> filtered.txt/g" - 将>> filtered.txt 附加到行,用于附加到最终输出文件。示例:
sed -n "7,12p" log.txt >> 过滤的.txt
sed -n "13,19p" log.txt >> 过滤的.txt
sed -n "20,26p" log.txt >> 过滤的.txt
sed -n "42,47p" log.txt >> 过滤的.txt
-
> run.bat - 最后,将最后几行打印到名为 run.bat 的批处理文件中
执行此文件后,您想要的内容将出现在filtered.txt中。
更新 2:
这是另一个适用于 Ubuntu 的版本(以前的版本是在 Windows 上编写的):
grep -nE "^DB2[0-9]+" log.txt | cut -f 1 -d " " | gawk '/E/{y=$0;print x, y};{x=$0}' | sed -e "s/:DB2[[:digit:]]\+[IE]//g" | gawk '{print "sed -n \""$1+1" ,"$2 "p\" log.txt" }' | sed -e "s/$/ >> filtered.txt/g" > run.sh
有两点不适用于以前的版本:
- 由于某种原因,
gawk '/E$/' 无法正常工作(它无法识别 E 位于行尾),所以我只输入了 /E/,因为在其他任何地方都找不到 E。李>
- 引用,
" 被转换为 ' 用于 gawk,因为它不喜欢双引号;之后,修改了最后一个 gawk 表达式中的引用