Я пытаюсь отредактировать файл json, чтобы печатать только те подгруппы, у которых есть какие-либо атрибуты, помеченные как «изменить»: false.
Json ниже:
{"group":{
"subgroup1":{
"attributes":[
{
"change":false,
"name":"Name"},
{
"change":false,
"name":"SecondName"},
],
"id":1,
"name":"MasterTest"},
"subgroup2":{
"attributes":[
{
"change":true,
"name":"Name"
},
{
"change":false,
"name":"Newname"
}
],
"id":2,
"name":"MasterSet"},
}}
Я пытался использовать команду:
cat test.json | jq '.group[] | select (.attributes[].change==false)
которые производят необходимый вывод, но с дубликатами. Кто-нибудь может здесь помочь? Или я должен использовать другую команду для достижения этого результата?
Не могу ответить на настоящий вопрос, пока вы не исправите JSON, но в целом cat anything | ... лучше заменить на <anything ...; когда вы даете своей программе настоящий дескриптор файла вместо FIFO, она может делать такие вещи, как распараллеливание ввода-вывода или определение длины файла перед чтением до конца (для информации о ходе выполнения) или пропуск (для гораздо более эффективной реализации такие инструменты, как tail или tac) и т. д.

.attributes[] перебирает атрибуты, и каждый шаг итерации дает свой собственный результат. Используйте фильтр any, который объединяет несколько значений в одно, в данном случае логическое значение со значением «хотя бы одно»:
.group[] | select(any(.attributes[]; .change==false))
{
"attributes": [
{
"change": false,
"name": "Name"
},
{
"change": false,
"name": "SecondName"
}
],
"id": 1,
"name": "MasterTest"
}
{
"attributes": [
{
"change": true,
"name": "Name"
},
{
"change": false,
"name": "Newname"
}
],
"id": 2,
"name": "MasterSet"
}
Еще один вопрос. Не могли бы вы также посоветовать, как переназначить этот JSON, если я хочу видеть в подгруппе «MasterSet» только атрибуты с «name» = «Newname»?
@strmgr Затем найдите подгруппу, соответствующую .name == "MasterSet", и map ее массив .attributes, чтобы он содержал только те элементы, которые соответствуют .name == "Newname": … | select(.name == "MasterSet").attributes |= map(select(.name == "Newname"))Демо . Обратите внимание, что это основано буквально на вашем последующем вопросе. Просто показать ранее сопоставленные атрибуты (имеющие .change==false) — это совершенно другой подход (.group[] | .attributes |= map(select(.change==false)) Демо), но он дает тот же результат для этого примера данных.
Большое спасибо еще раз! Мне очень помогает!
Еще один вопрос - есть ли возможность сортировать печать атрибутов в этом массиве? Бывший. первый "name":"Name" и второй "change":false? Как это сделать также в верхней иерархии ex. первый "MasterSet" и второй "MasterTest"
Я думаю, что это будет последний вопрос, наконец :)
Объекты @strmgr JSON не имеют порядка полей, только массивы имеют порядок элементов. Итак, если вы все равно деструктурируете объект, вы можете сначала собрать значения его полей в массив, а затем отсортировать и деструктурировать его. Это можно применить к объекту, удерживаемому .group (вашем внешнему корпусу), который вы деструктурировали с помощью .group[]. Итак, замените .group[] на [.group[]] | sort_by(.name)[], и все готово. Однако с внутренним корпусом это зависит от того, что вы на самом деле имеете в виду (может быть, я просто неправильно понял). Упорядочить элементы массива .attributes просто: поскольку это массив… (1/3)
… просто дополните свой фильтр | .attributes |= sort_by(.name, .change), и он будет отсортирован по критерию, указанному первым, а в случае ничьей — по критерию, заданному вторым. Но если вы хотите видеть упорядоченными сами его элементы, это становится сложной задачей, потому что это объекты, которые, как указано выше, не имеют порядка и, как таковые, просто не могут быть отсортированы должным образом. Конечно, поля отображаются в одном, но это на усмотрение процессора JSON. Любой (другой) процессор, примененный впоследствии, вполне может игнорировать этот порядок. Куда пойти отсюда? Вы можете «пойти на этот риск» и… (2/3)
… заманить процессор jq к созданию определенного порядка, создав новые объекты и предоставив ему поля в выбранном вами порядке. Используйте сопоставление для доступа ко всем элементам массива .attributes, как в | .attributes |= map({name, change}). Другой способ — собрать значения полей в массив, но на этот раз вместе с именами полей отсортировать массив по последним и сохранить значения. Это надежно даст вам порядок, но за счет потери (неупорядоченной) структуры объекта в упорядоченном массиве: | .attributes |= map(to_entries | sort_by(.key) | map(.value)). (3/3)
Мне кажется, что дубликат - это НЕ дубликат, а условие, возникающее из-за вложенной подгруппы, которая создает впечатление дубликата. Вы должны посмотреть, есть ли переключатель для пропуска подгрупп обработки, когда верхний уровень удовлетворяет условию, тем самым избегая предполагаемого дублирования.
Это недопустимый json, и у jq могут возникнуть проблемы с его разбором. Также: каков ожидаемый результат?