我有一个像这样的JSON对象数组。
[
{
"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"
}
]我需要向bash脚本中计算的每个对象添加一个名为days-idle的键,其中包含一个值。这就是我在每个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"
}我知道您可以用jq添加一个键,但是不知道如何添加一个键,值对,其中值是bash变量。
发布于 2021-06-28 10:26:04
假设您想用特定的.id值将新键添加到元素中,则$id:
jq --arg id "$id" --arg idle "$daysIdle" \
'( .[] | select(.id == $id)."days-idle" ) |= $idle' file这将使用我们想要修改的.id来选择数组元素,然后使用我们希望它具有的特定值向该元素添加(实际上是更新) ."days-idle"键。
如果."days-idle"应该是从."last-disconnection-time"时间戳到现在之间的时间,那么您可以像这样更新JSON中的所有元素:
jq 'def dayssince: ((now - (sub("[.].*"; "Z") | fromdate))/86400) | round;
map(. += { "days-idle": (."last-disconnection-time" | dayssince) })' filesub()调用将截断点处的时间戳,并将其末尾替换为Z。这是因为fromdate在它可以解析的时间戳类型上有一些限制,并且不能处理原始时间戳字符串的子秒精度。
为了保持代码的整洁,我决定将时间戳的实际计算时间作为一个名为jq函数的dayssince。
生成的JSON (在2021年6月28日运行时):
[
{
"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
}
]发布于 2020-12-02 21:23:41
首先,我将假设Bash变量中有JSON对象数组,因此让我们从以下内容开始:
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"
}
]'接下来,我将假设$daysIdle也是变量,包含一个数字:
bash$ daysIdle=3现在,我们可以通过$object回显jq来添加该变量。
bash$ echo "$object" | jq --arg daysIdle "$daysIdle" '.[]."days-idle" = ($daysIdle | tonumber)'这方面有一些重要的注意事项。如果对象实际上位于文件中或来自其他流(如cURL ),则只需替换适当的echo $object即可。其次,我假设您希望它是一个JSON数字,而不是--arg通常创建的字符串,因此我在其中有一个过滤器来修复这个问题。最后,请注意,我使用--arg选项向jq传递值。这比尝试将值嵌入JSON筛选器字符串本身要好得多,也比尝试将值嵌入JSON过滤器字符串本身安全得多,而且不会在其中造成语法错误。如果不能转换为一个数字,它将抛出一个错误,但是它不允许任意注入到过滤器字符串中。这么说,让我们看看输出:
[
{
"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
}
]https://unix.stackexchange.com/questions/523547
复制相似问题