标准 unix 命令行工具(grep、cut、sed 等)都一次运行一行。几乎总是这样,这很棒。
不过我正在尝试解析一些 postgresql 慢查询日志。每个条目在开始处都有一些内容(日期时间、持续时间),然后是 SQL 查询。 SQL 查询可能有换行符,因此日志文件中的每个“条目”可能会多于 1 行(因为查询中的换行符会直接放入日志文件中,而不是转义)。我想以某种方式将这些行“合并”在一起,以便 1 行 = 1 个日志文件条目。现在,有时一个条目完全在一行上,有时一个条目分布在多达 10 行中。
有没有一个unix工具可以以某种方式“lineify”这个文件?我想给它一个(PCRE)正则表达式,它会根据它分割行/标准输入。此正则表达式出现之间的所有实际换行符应替换为"\n"
或 我可以指定的内容。
可能有一个衬垫可以用 perl 来做到这一点,但我想在我自己制作之前看看是否有人已经制作了这个程序。
更新:我可以提供示例数据,但我想知道一般问题。 SQL Server 可能会生成多行日志文件。我想要一个通用的解决方案将任何文件转换为换行符分隔的 unix-y 样式文件。
答案1
使用 gawk,您可以使用 PCRE 表达式(的子集)作为寄存器分隔符 ( RS
),定义不同的输出寄存器分隔符 ( ORS
) 并替换\n
。
例子:
gawk 'BEGIN {RS="[ ]*;\n"; ORS="\n===\n"}
{gsub("\n","\\n"); print} '
在这个例子中:
[ ]*;\n
寄存器在输入中用分隔- 寄存器在输出中用“\n===\n”分隔
答案2
逐行解析日志文件行并抑制所有 \n。当你看到一个新条目时,除了第一次之外,首先写\n。
你说了Each entry has some stuff at the start (datetime, duration)
,但你没有举例。好吧,我就叫它NEW_ENTRY,你可以修改。
inStatement=0
cat logfile | while read -r line; do
if [[ ${inStatement} = 0 ]]; then
inStatement=1
else
[[ ${line} = NEW_ENTRY* ]] && echo
fi
echo -n "${line} "
done
echo