如何用jq按连续eventId分组合并message并拆分Time开头消息
解决方案
以下是符合需求的jq脚本,解决了超大eventId的精度问题,同时实现了指定的分组合并逻辑:
.events | reduce .[] as $item ( []; ($item.eventId | tonumber) as $currentId | if length == 0 then [{ eventIdStart: $item.eventId, eventIdEnd: $item.eventId, message: $item.message }] else last as $last | ($last.eventIdEnd | tonumber) as $lastId | if ($item.message | startswith("# Time")) or ($currentId != $lastId + 1) then . + [{ eventIdStart: $item.eventId, eventIdEnd: $item.eventId, message: $item.message }] else .[:-1] + [{ eventIdStart: $last.eventIdStart, eventIdEnd: $item.eventId, message: $last.message + "\n" + $item.message }] end end ) | { mergedEvents: . }
关键逻辑说明
超大eventId处理:
使用tonumber将eventId转换为jq的bigint类型,避免1.7版本对超大整数的精度丢失问题——只要输入的eventId是合法的整数字符串或数值,就能正确处理连续判断。分组合并规则:
- 遍历events数组时,维护当前的分组列表。
- 若当前条目是第一个元素,直接初始化新分组。
- 对于后续元素,检查两个触发新分组的条件:
- 当前条目的
message以# Time开头 - 当前条目的eventId与上一个分组的结束eventId数值不连续(差值不为1)
- 当前条目的
- 不满足新分组条件时,将当前条目的message追加到上一个分组的message中,并更新分组的结束eventId。
示例输入输出
输入JSON
{ "events": [ {"eventId": "12345678901234567890", "message": "line 1"}, {"eventId": "12345678901234567891", "message": "line 2"}, {"eventId": "12345678901234567892", "message": "# Time: 2024-01-01"}, {"eventId": "12345678901234567893", "message": "line 3"}, {"eventId": "12345678901234567895", "message": "line 4"} ] }
输出JSON
{ "mergedEvents": [ { "eventIdStart": "12345678901234567890", "eventIdEnd": "12345678901234567891", "message": "line 1\nline 2" }, { "eventIdStart": "12345678901234567892", "eventIdEnd": "12345678901234567892", "message": "# Time: 2024-01-01" }, { "eventIdStart": "12345678901234567893", "eventIdEnd": "12345678901234567893", "message": "line 3" }, { "eventIdStart": "12345678901234567895", "eventIdEnd": "12345678901234567895", "message": "line 4" } ] }
自定义调整
- 如果需要修改message的合并分隔符,将脚本中的
"\n"替换为你需要的字符串(比如空格" ")即可。 - 如果eventId本身是数值类型而非字符串,可去掉
| tonumber,直接使用$item.eventId和$last.eventIdEnd进行数值比较。
内容的提问来源于stack exchange,提问作者P.Lonnie
相关产品推荐
相关产品推荐

