Com um campo Json como o abaixo, se eventId for um valor contínuo, gostaria de adicionar o valor do campo de mensagem.
Entretanto, mesmo que eventId seja contínuo, se o campo de mensagem começar com # Hora, o campo de mensagem será separado.
Este é o campo original do Json.
{
"events": [
{
"message": "# Time: 1",
"eventId": "38636469249093328935961608873790523617989208925384015872"
},
{
"message": ", 2, 3",
"eventId": "38636469249093328935961608873790523617989208925384015873"
},
{
"message": "# Time: 11",
"eventId": "38636469249093328935961608873790523617989208925384015875"
},
{
"message": "# Time: 12",
"eventId": "38636469249093328935961608873790523617989208925384015876"
},
{
"message": "# Time: A",
"eventId": "1"
},
{
"message": ", B, C",
"eventId": "2"
},
{
"message": "# Time: C",
"eventId": "3"
},
{
"message": "# Time: D",
"eventId": "5"
}
]
}
É assim que eu quero que fique:
[
{
"message": "# Time: 1, 2, 3"
},
{
"message": "# Time: 11"
},
{
"message": "# Time: 12"
},
{
"message": "# Time: A , B, C"
},
{
"message": "# Time: C"
},
{
"message": "# Time: D"
}
]
Já fiz uma pergunta sobre isso antes e recebi uma resposta de uma ótima pessoa. (Obrigado pmf.)
Depois disso, tentei o meu melhor para refinar um pouco mais, mas não funcionou, então perguntei mais uma vez.
Primeiro, quando executei este JQ pela primeira vez, obtive os seguintes resultados.
jq -r '.events
| reduce .[1:][] as $i (.[:1];
if ((.[-1].eventId | tonumber + 1 | tostring) != $i.eventId) or ($i.message | startswith("# Time:")) then
. += [$i]
else
.[-1].message += " " + $i.message
end
)
| del(.[].eventId)
'
[
{
"message": "# Time: 1"
},
{
"message": ", 2, 3"
},
{
"message": "# Time: 11"
},
{
"message": "# Time: 12"
},
{
"message": "# Time: A , B, C"
},
{
"message": "# Time: C"
},
{
"message": "# Time: D"
}
]
Eu vi isso como um problema de ponto flutuante e queria comparar esse número com a própria string, então criei uma função como a seguinte, mas não funcionou.
jq '
# Function to add one to a large number represented as a string
def add_one(num):
(num | split("") | reverse | map(tonumber)) as $digits
| reduce range(0; length) as $i ([];
. + if $i == 0 or .[-1] == 10 then
[($digits[$i] + 1) % 10]
else
[$digits[$i]]
end
)
| reverse | map(tostring) | join("");
# Process events and check continuity
.events
| map(.eventId |= tostring) # Ensure all eventIds are strings
| reduce .[1:][] as $i (.[:1];
if (add_one(.[-1].eventId) != $i.eventId) or ($i.message | startswith("# Time:")) then
. += [$i]
else
.[-1].message += " " + $i.message
end
)
| del(.[].eventId)
'
[
{
"message": "# Time: 1"
},
{
"message": ", 2, 3"
},
{
"message": "# Time: 11"
},
{
"message": "# Time: 12"
},
{
"message": "# Time: A"
},
{
"message": ", B, C"
},
{
"message": "# Time: C"
},
{
"message": "# Time: D"
}
]
Pesquisando mais, encontrei um comando chamado gojq, mas gostaria de testá-lo primeiro para ver se é possível com jq.
Estou usando o jq versão 1.7.1.
Se você puder confiar na ordem dos itens e que apenas as mensagens corretas começam com
#
, você só precisa verificar as ocorrências do último.Demonstração
No entanto, implementar os requisitos mais rigorosos não é muito mais difícil. Note que transportar o
eventId
for comparison requer sua remoção depois.Demonstração
Saída: