Json

jq - 有條件地將一個值設置為另一個值

  • October 20, 2021

我需要使用 jq 將 json doc 中的欄位值設置為三個值之一,具體取決於哪個存在。名義上,這看起來像:set X to (if A exists, else if B exists, else if C exists, else "").

我有一個範例 json doc,如下所示:

{
 "name": "0230",
 "publish_date": "2007-08-18",
 "abc_severity": "",
 "def_severity": "medium",
 "ghi_severity": "negligible"
}

我想創建一個欄位Severity並將其值設置abc_severity為非空值或空值。如果它為 null 或為空,我想將其設置為def_severity,如果它為 null 或為空,我想將其設置為ghi_severity。如果這三個都為 null 或為空,則可以使用空值創建""。所以這種情況下的輸出將是:

{
 "name": "0230",
 "publish_date": "2007-08-18",
 "abc_severity": "",
 "def_severity": "medium",
 "ghi_severity": "negligible",
 "Severity": "medium"
}

以下是我似乎能夠得到的最接近的:

'. | if .abc_severity? then .Severity=.abc_severity else if .def_severity? then .Severity=.def_severity else if .ghi_severity? then .Severity=.ghi_severity else .Severity="" end end end'

但是即使存在一個或多個其他值,的值Severity也始終是。""我確定我在這裡忽略了一些簡單的東西,我似乎無法理解。

空字元串仍然是字元串,因此.abc_severity?會給您一個空字元串,而不是null(或false)。另外請注意,問號的意思大致是“null如果此鍵不存在則替換為”。在範例中,所有三個鍵都存在,並且它們的值不存在null

如果您一直使用null空值,您的jq表達式看起來像

.Severity = (.abc_severity // .def_severity // .ghi_severity )

上面的表達式會選擇三個不是的值中的第一個null,測試最左邊的第一個然後向右移動,或者null如果它們都是null。但這現在行不通,因為我們必須像處理空字元串一樣處理null.

我們可以通過引入一個輔助函式來做到這一點(以減少我們的輸入):

def n: if . == "" then null else . end;
.Severity = ((.abc_severity|n) // (.def_severity|n) // (.ghi_severity|n) // "")

如果字元串不為空,我們的輔助函式n會按原樣返回字元串;否則,它返回null。使用鍊式//操作符,我們選擇三個不是的第一個值null,當被看穿時n,或者如果所有三個值都是,則選擇空字元串null

使用您的數據在命令行上測試上述內容:

$ jq 'def n: if . == "" then null else . end; .Severity = ((.abc_severity|n) // (.def_severity|n) // (.ghi_severity|n) // "")' file
{
 "name": "0230",
 "publish_date": "2007-08-18",
 "abc_severity": "",
 "def_severity": "medium",
 "ghi_severity": "negligible",
 "Severity": "medium"
}

引用自:https://unix.stackexchange.com/questions/672784