Eu tenho uma matriz JSON de objetos assim.
[
{
"id" : "tmp1387816934708382026",
"owner" : "john",
"x11-display" : ":5",
"x11-authority" : "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections" : 1,
"creation-time" : "2019-05-14T14:12:14.989287Z",
"last-disconnection-time" : "2019-05-31T18:58:42.851223Z"
},
{
"id" : "tmp4241942441012516520",
"owner" : "mike",
"x11-display" : ":10",
"x11-authority" : "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections" : 0,
"creation-time" : "2019-05-17T16:23:05.891531Z",
"last-disconnection-time" : "2019-05-19T11:23:30.844797Z"
}
]
Preciso adicionar uma chave nomeada days-idle
com um valor para cada objeto calculado dentro do meu script bash. É isso que procuro em cada objeto JSON.
{
"id" : "tmp1387816934708382026",
"owner" : "mike",
"x11-display" : ":5",
"x11-authority" : "/run/user/mike/dcv/tmp1387816934708382026.xauth",
"num-of-connections" : 1,
"creation-time" : "2019-05-14T14:12:14.989287Z",
"last-disconnection-time" : "2019-05-31T18:58:42.851223Z",
"days-idle" : "$daysIdle"
}
Eu sei que você pode adicionar uma chave, jq
mas não tinha certeza de como adicionar um par de chave e valor onde o valor é uma variável bash.
Responder1
Supondo que você queira adicionar sua nova chave ao elemento com um .id
valor específico $id
:
jq --arg id "$id" --arg idle "$daysIdle" \
'( .[] | select(.id == $id)."days-idle" ) |= $idle' file
Isso seleciona o elemento da matriz com o .id
que queremos modificar e depois adiciona (na verdadeatualizações) a ."days-idle"
chave desse elemento com o valor específico que queremos que ele tenha.
Deve ."days-idle"
ser o tempo entre o ."last-disconnection-time"
carimbo de data/hora eagora, então você pode atualizar todos os elementos no JSON assim:
jq 'def dayssince: ((now - (sub("[.].*"; "Z") | fromdate))/86400) | round;
map(. += { "days-idle": (."last-disconnection-time" | dayssince) })' file
A sub()
chamada truncará o carimbo de data/hora no ponto e substituirá o final dele por Z
. Isso se deve ao fato de fromdate
ser um pouco restritivo no tipo de carimbo de data/hora que ele pode analisar e não manipula a precisão de menos de um segundo da string de carimbo de data/hora original.
Decidi colocar o cálculo real do número de dias desde o timestamp como uma jq
função chamada dayssince
, apenas para manter o código organizado.
O JSON resultante (quando executado em 28 de junho de 2021):
[
{
"id": "tmp1387816934708382026",
"owner": "john",
"x11-display": ":5",
"x11-authority": "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections": 1,
"creation-time": "2019-05-14T14:12:14.989287Z",
"last-disconnection-time": "2019-05-31T18:58:42.851223Z",
"days-idle": 759
},
{
"id": "tmp4241942441012516520",
"owner": "mike",
"x11-display": ":10",
"x11-authority": "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections": 0,
"creation-time": "2019-05-17T16:23:05.891531Z",
"last-disconnection-time": "2019-05-19T11:23:30.844797Z",
"days-idle": 771
}
]
Responder2
Primeiro, vou assumir que você tem o array de objetos JSON em uma variável Bash, então vamos começar com isso:
bash$ object='[
{
"id" : "tmp1387816934708382026",
"owner" : "john",
"x11-display" : ":5",
"x11-authority" : "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections" : 1,
"creation-time" : "2019-05-14T14:12:14.989287Z",
"last-disconnection-time" : "2019-05-31T18:58:42.851223Z"
},
{
"id" : "tmp4241942441012516520",
"owner" : "mike",
"x11-display" : ":10",
"x11-authority" : "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections" : 0,
"creation-time" : "2019-05-17T16:23:05.891531Z",
"last-disconnection-time" : "2019-05-19T11:23:30.844797Z"
}
]'
A seguir, assumirei que $daysIdle
também é variável e contém um número:
bash$ daysIdle=3
Agora, podemos repetir o $object
through jq
para adicionar essa variável.
bash$ echo "$object" | jq --arg daysIdle "$daysIdle" '.[]."days-idle" = ($daysIdle | tonumber)'
Algumas notas importantes sobre isso. Se os objetos estiverem realmente em um arquivo ou vindo de algum outro fluxo como cURL, basta substituir echo $object
o que for apropriado. Em segundo lugar, presumo que você o queira como um número JSON e não como uma string que --arg
normalmente é criada, então tenho um filtro para corrigir isso. Por último, observe que utilizo a --arg
opção para jq
passar o valor. Isso é muito melhor e mais seguro do que tentar incorporar o valor na própria string do filtro JSON e não causará um erro de sintaxe nela. Irá gerar um erro se não puder converter para um número, mas não permitirá a injeção arbitrária na string do filtro. Dito isso, vamos ver o resultado:
[
{
"id": "tmp1387816934708382026",
"owner": "john",
"x11-display": ":5",
"x11-authority": "/run/user/john/dcv/tmp1387816934708382026.xauth",
"num-of-connections": 1,
"creation-time": "2019-05-14T14:12:14.989287Z",
"last-disconnection-time": "2019-05-31T18:58:42.851223Z",
"days-idle": 3
},
{
"id": "tmp4241942441012516520",
"owner": "mike",
"x11-display": ":10",
"x11-authority": "/run/user/mike/dcv/tmp4241942441012516520.xauth",
"num-of-connections": 0,
"creation-time": "2019-05-17T16:23:05.891531Z",
"last-disconnection-time": "2019-05-19T11:23:30.844797Z",
"days-idle": 3
}
]