我想格式化我的服务器日志,以便在我执行" tail -f"时可以轻松阅读。
我的日志看起来像:
{"item1":"ab","item2":"cdef","item3":"ghi"}
{"item1":"abc","item2":"defgh","item3":"i"}
我想获得:
var1=ab__ | var2=cdef_ | var3=ghi
var1=abc_ | var2=defgh | var3=i__
哪里' _'是一个白色的空间。
现在我用:
sed -E 's/.*item1":"(.*)","item2":"(.*)","item3":"(.*)".*/var1=\1 | var2=\2 | var3=\3/'
我得到了:
var1=ab | var2=cdef | var3=ghi
var1=abc | var2=defgh | var3=i
可以设置捕获的组\ 1 \ 2 \ 3的长度吗?用空格填充或截断它们?
我想修复每个字段的长度(填充或截断)并实时流式传输我的日志。
答案 0 :(得分:1)
评论已经在推荐jq
。
这是一种方法:
$ jq -r '[(.item1, .item2, .item3)] | @tsv' log.json
ab cdef ghi
abc defgh i
请注意@tsv
过滤器是在jq
1.5版本中引入的,所以如果您使用的是1.4,那么可能需要升级。:)< / SUP>
如果你想要垂直条,你可以在数组中添加它们:
$ jq -r '[(.item1, "|", .item2, "|", .item3)] | @tsv' log.json
ab | cdef | ghi
abc | defgh | i
请注意,@tsv
会在每个字段之间添加一个标签,因此这可能与您想要的完全不同。但是,它可以很容易地被bash解析:
$ while IFS=$'\t' read one two three; do \
printf 'var1=%-4s | var2=%-5s | var3=%-4s\n' "$one" "$two" "$three"; \
done < <(jq -r '[(.item1, .item2, .item3)] | @tsv' log.json)
var1=ab | var2=cdef | var3=ghi
var1=abc | var2=defgh | var3=i
或者,如果具体格式不重要,你只想要排队,也许这就是:
$ jq -r '[(.item1, "|", .item2, "|", .item3)] | @tsv' log.json | column -t
ab | cdef | ghi
abc | defgh | i
当然,这不会处理tail -f
,它只是涵盖格式化。如果您希望能够处理流,则可能需要在循环中执行此操作。例如:
tail -F "$logfile" | while read -r line; do
jq -r '[(.item1, .item2, .item3)] | @tsv' <<< "$line" |
while IFS=$'\t' read one two three; do
printf 'var1=%-4s | var2=%-5s | var3=%-4s\n' "$one" "$two" "$three"
done
done
请注意,此处选择的格式化选项是printf
,因为所有其他解决方案都需要了解输入数据的最大长度。使用printf
,我们假设您已经知道最大长度,并在格式字符串中对其进行了解释。
答案 1 :(得分:0)
短 jq
+ printf
解决方案:
jq -rs '.[] |
@sh "printf \"var1=%-8s| var2=%-8s| var3=%-8s\n\" \(.item1) \(.item2) \(.item3)"' log | sh
输出:
var1=ab | var2=cdef | var3=ghi
var1=abc | var2=defgh | var3=i
-s
- 不是为输入中的每个 JSON 对象运行过滤器,而是将整个输入流读入一个大型数组并仅运行一次过滤器@sh
- 输入转义适合在 POSIX shell的命令行中使用答案 2 :(得分:0)
将您的sed输出传输到column -t
以制作表格。