JQ: выберите, когда значение атрибута существует в массиве bash
Я использую JQ 1.4. Я пытаюсь выбрать элементы, когда VPCZoneIdentifier существует в моем $selected_subnets
(переменная bash).
selected_subnets="valueA valueB"
input='{"elements":[
{"name": "nameA", "VPCZoneIdentifier": "valueA"},
{"name": "nameB", "VPCZoneIdentifier": "valueB"},
{"name": "nameC", "VPCZoneIdentifier": "valueC"}
]}'
test
а также match
fn доступны только на v1.5.
2 ответа
Это немного сложно, но это может быть сделано с reduce
, Все это может выглядеть так:
selected_subnets_json=$(echo "\"$selected_subnets\"" | jq -c -M 'split(" ")')
echo "$input" | jq -M '.elements = [.elements[] | select(.VPCZoneIdentifier as $id | '"$selected_subnets_json"' | reduce .[] as $v (false; . or $id == $v))]'
Первая часть делает массив JSON из списка оболочки:
$ echo "\"$selected_subnets\"" | jq -c -M 'split(" ")'
["valueA","valueB"]
Вторая часть использует reduce
фильтр для сравнения .VPCZoneIdentifier
свойство со всеми элементами этого массива. С selected_subnets_json
переменная, развернутая в нее, фильтр выглядит следующим образом:
.elements = [
.elements[] |
select(.VPCZoneIdentifier as $id |
[ "valueA", "valueB" ] | reduce .[] as $v (false; . or $id == $v))
]
То есть elements
свойство перезаписывается теми элементами, которые соответствуют критерию выбора
.VPCZoneIdentifier as $id | [ "valueA", "valueB" ] | reduce .[] as $v (false; . or $id == $v))
Об этом первая часть помнит VPCZoneIdentifier
как $id
(так как .
будет означать что-то совсем другое) и
[ "valueA", "valueB" ] | reduce .[] as $v (false; . or $id == $v))
является или сокращением массива подсети. Расширяется до false or $id == "valueA" or $id == "valueB"
в этом случае.
Если вы предпочитаете иметь все это за один раз, вы можете написать
echo "$input" | jq -M '.elements = [.elements[] | select(.VPCZoneIdentifier as $id | ("'"$selected_subnets"'" | split(" ")) | reduce .[] as $v (false; . or $id == $v))]'
Это работает в основном так же, за исключением разделения $selected_subnets
делается встроенным
Вы можете установить переменные из командной строки, чтобы они были доступны в ваших запросах, используя --arg
вариант. Затем вы можете отфильтровать элементы, используя select
фильтр. Учитывая массив значений, вы можете сделать "value in array"
сделайте следующее:
value == (array[])
Таким образом, ваш фильтр будет иметь следующую структуру:
.elements | map(
select(
.VPCZoneIdentifier == ($subnets | split(" ")[])
)
)
Собираем все это вместе с вашими переменными:
$ echo $input | jq --arg subnets "$selected_subnets" '.elements | map(select(.VPCZoneIdentifier == ($subnets | split(" ")[])))'
[
{
"name": "nameA",
"VPCZoneIdentifier": "valueA"
},
{
"name": "nameB",
"VPCZoneIdentifier": "valueB"
}
]