我正在使用JQ过滤事物列表,然后针对发现的每个事物-通过从子键中提取值将其重新格式化为单个字符串。
问题是缺少子键之一,因此省略了整行。
请考虑以下示例文档:
{
"items": [
{
"id": "A",
"active": true,
"tags": [
{ "name": "foo", "value": 1 }
]
},
{
"id": "B",
"active": true,
"tags": [
{ "name": "foo", "value":1 },
{"name": "bar", "value":2}
]
},
{
"id": "C",
"active": false,
"tags": [
{ "name": "foo", "value":1 },
{ "name": "baz", "value":3 }
]
}
]
}
现在,我想选择所有活动项,并为每行创建一个描述项ID的行以及其foo
和bar
标签的值。
最初,我已经做了类似的事情:
jq -r '
.items[] |
select ( .active == true ) |
( .id + " -> [" +
( .tags[] | select( .name == "foo" ) | .value | tostring ) +
", " +
( .tags[] | select( .name == "bar" ) | .value | tostring ) +
"]"
)
'
但是由于bar
仅包含在项目B
中,因此项目A
的行被过滤掉了。
有没有一种方法可以使子选择成为可选内容,以便如果选择失败,我会得到一个空字符串或类似的内容?
答案 0 :(得分:2)
您可以使用if ... then ... else ... end
或也许//
来修补查询,但最好也解决其他一些问题,例如如下:
.items[]
| select ( .active == true )
| .id + " -> ["
+ (.tags | map(select(.name == "foo") | .value) | join(";"))
+ ", "
+ (.tags | map(select(.name == "bar") | .value) | join(";"))
+ "]"
对于jq版本1.5或更早版本,您需要添加对tostring
的调用,或使用字符串插值,例如
.items[]
| select ( .active == true )
| .id
+ " -> [\(.tags | map(select(.name == "foo") | "\(.value)") | join(";") ), "
+ "\(.tags | map(select(.name == "bar") | "\(.value)" ) | join(";"))"
+ "]"
first
和字符串插值的变量.items[]
| select ( .active == true )
| (first(.tags[] | select(.name == "foo") | .value) // "") as $v
| (first(.tags[] | select(.name == "bar") | .value) // "") as $w
| "\(.id) -> [\($v), \($w)]"
使用字符串插值可以避免使用tostring
的潜在麻烦。