Как объединить объекты jq JSON, созданные фильтрами через запятую - PullRequest
1 голос
/ 06 января 2020

Я пытаюсь использовать jq для преобразования некоторых флагов командной строки в JSON эквивалент.

Флаги выглядят следующим образом, где идея состоит в том, чтобы преобразовать (необязательный) флаг f в JSON поле "foo" и (необязательно) флаг b в поле JSON "bar":

{
  "flags": [
    "f1",
    "b2",
    "f3b4",
    "b6f5"
  ]
}

Получить поля foo очень просто:

.flags[] | match("f([0-9][0-9]*)") | .captures[0].string | tonumber | { "foo": . }

То же самое для полей бара (скажите, если есть лучшие способы сделать это с помощью jq):

.flags[] | match("b([0-9][0-9]*)") | .captures[0].string | tonumber | { "bar": . }

Как объединить выходные данные этих двух фильтров так, чтобы каждая строка входных флагов отображалась в один JSON объект без / одного / обоих необязательных полей?

Двумя соответствующими механизмами являются оператор запятой jq (для разделения одного потока между несколькими фильтрами) и оператор + jq (для объединения объектов в один объект). Применение оператора запятой является простым:

.flags[] | (match("f([0-9][0-9]*)") | .captures[0].string | tonumber | { "foo": . }), (match("b([0-9][0-9]*)") | .captures[0].string | tonumber | { "bar": . })

Однако, это дает отдельный объект для каждого совпадения:

{
  "foo": 1
}
{
  "bar": 2
}
{
  "foo": 3
}
{
  "bar": 4
}
{
  "foo": 5
}
{
  "bar": 6
}

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

{
  "foo": 1
}
{
  "bar": 2
}
{
  "foo": 3,
  "bar": 4
}
{
  "foo": 5,
  "bar": 6
}

Как лучше всего добиться этого с помощью jq?

1 Ответ

1 голос
/ 06 января 2020

Функция захвата кажется подходящей для вашей задачи.

Из руководства : capture(regex; flags) "Собирает именованные захваты в объекте JSON с именем каждого захвата как ключ и совпавшую строку как соответствующее значение. "

jq '.flags[]
| capture("(?<foo>^f\\d+$)"),
  capture("(?<bar>^b\\d+$)"),
  capture("(?<foo>f\\d+)(?<bar>b\\d+)"),
  capture("(?<bar>b\\d+)(?<foo>f\\d+)")
| .[] |= ( sub("\\D"; "") | tonumber )'

Строки захвата создают следующие объекты:

{
  "foo": "f1"
}
{
  "bar": "b2"
}
{
  "foo": "f3",
  "bar": "b4"
}
{
  "bar": "b6",
  "foo": "f5"
}

Последняя строка обновляет значения в этих объектах, удаляя не -значение и преобразование результата в число.

...