我有一個像這樣的 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"
}
]
我需要days-idle
向 bash 腳本中計算的每個物件添加一個以值命名的鍵。這就是我在每個 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 變數。
答案1
假設您想將新鍵新增至具有特定值的元素.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) })' file
此sub()
呼叫將截斷點處的時間戳並將其末尾替換為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
}
]
答案2
首先,我假設 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
through來jq
加入該變數。
bash$ echo "$object" | jq --arg daysIdle "$daysIdle" '.[]."days-idle" = ($daysIdle | tonumber)'
關於這一點的一些重要說明。如果物件實際上位於文件中或來自其他串流(例如 cURL),則只需替換echo $object
適當的內容即可。其次,我假設您希望它作為 JSON 數字而不是--arg
通常創建的字串,因此我在其中有一個過濾器來解決這個問題。最後,請注意,我使用--arg
選項來jq
傳遞值。這比嘗試將值嵌入到 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
}
]