Виберіть об'єкти на основі значення змінної в об'єкті за допомогою jq


236

У мене є такий файл json:

{
    "FOO": {
        "name": "Donald",
        "location": "Stockholm"
    },
    "BAR": {
        "name": "Walt",
        "location": "Stockholm"
    },
    "BAZ": {
        "name": "Jack",
        "location": "Whereever"
    }
}

Я використовую jq і хочу отримати "ім'я" елементів об'єктів, де "location" - "Стокгольм".

Я знаю, що можу отримати всі імена

cat json | jq .[] | jq ."name"
"Jack"
"Walt"
"Donald"

Але я не можу зрозуміти, як надрукувати лише певні об'єкти, враховуючи значення підрозділу (тут "location" : "Stockholm").

Відповіді:



184

Щоб отримати потік лише імен:

$ jq '.[] | select(.location=="Stockholm") | .name' json

виробляє:

"Donald"
"Walt"

Щоб отримати потік відповідних пар (ім'я ключа, атрибут "ім'я"), врахуйте:

$ jq -c 'to_entries[]
        | select (.value.location == "Stockholm")
        | [.key, .value.name]' json

Вихід:

["FOO","Donald"]
["BAR","Walt"]

Він хоче, щоб весь об’єкт був заснований на розташуванні: "Я не можу зрозуміти, як друкувати лише певні об'єкти, враховуючи значення підпункту"
Fo.

2
Труба після вибору вам не потрібна: $ jq '. [] | виберіть (.location == "Стокгольм"). ім'я 'json
Діпак

Створення nameключа змінного (використовувати функцію оболонки з в $1якості параметра) не працює: termux-contact-list |jq -r '.[] | select(.name=="$1")|.number'. Я це називаю так cool_fn Name1. Однак це працює:termux-contact-list |jq -r '.[] | select(.name=="Name1")|.number'
Тимо

Ось рішення, якщо воно вам подобається змінним.
Тимо

27

У мене було подібне пов'язане питання: Що робити, якщо ви хочете повернути оригінальний формат об'єкта (з ключовими назвами, наприклад, FOO, BAR)?

Jq забезпечує to_entriesі from_entriesперетворює між об'єктами і масивами пар ключ-значення. Це разом з mapнавколо вибору

Ці функції перетворюються між об'єктом і масивом пар ключ-значення. Якщо to_entries передається об'єкт, то для кожного запису k: v у вхідному масиві вихідний масив включає {"ключ": k, "значення": v}.

from_entries робить зворотне перетворення, а with_entries (foo) - це скорочення для to_entries | карта (foo) | from_entries, корисний для виконання певної операції з усіма ключами та значеннями об'єкта. from_entries приймає ключ, ключ, ім'я, ім'я, значення та значення як ключі.

jq15 < json 'to_entries | map(select(.value.location=="Stockholm")) | from_entries'

{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

Використання with_entries скорочення, це стає:

jq15 < json 'with_entries(select(.value.location=="Stockholm"))'
{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

1
Одна річ, яка мене постійно кусає, - це те, що потрібно пам’ятати, що під час використання with_entries(), як правило, ти хочеш також використовувати.value в selectпункті. Це пов’язано з тим, що to_entriesмакрос перетворює задані записи в .keyі .valueпари, що також відбувається з with_entries.
Яакко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.