в jq выбор может быть необязательным (то есть, если ничего не найдено - не отфильтровывать элемент) - PullRequest
0 голосов
/ 16 ноября 2018

Я использую 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 }
      ]
    }
  ]
}

Теперь я хочу выбрать все активные элементы и создать для каждой отдельной строки, описывающейидентификатор элемента, а также значение его тегов foo и bar.

Изначально я сделал что-то вроде этого:

jq -r '
   .items[] | 
   select ( .active == true ) | 
   ( .id + " -> [" + 
     ( .tags[] | select( .name == "foo" ) | .value | tostring ) +
     ", " +
     ( .tags[] | select( .name == "bar" ) | .value | tostring ) +
     "]"
   )
'

Но поскольку barвключается только в элемент B, строка для элемента A отфильтровывается.

Есть ли способ сделать дополнительный выбор необязательным, чтобы в случае неудачного выбора я получал пустую строку или что-то в этом роде?как это?

1 Ответ

0 голосов
/ 16 ноября 2018

Вы можете пропатчить ваш запрос, используя 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.

...