Как я могу преобразовать последовательность "ключ: значение" в JSON? - PullRequest
0 голосов
/ 31 октября 2018

hokay, я пытаюсь написать сценарий, который берет информацию из yum - repolist all и помещает ее в симпатичный JSON для использования в некоторых сборах данных. Сейчас у меня вывод моей команды yum выглядит следующим образом.

Все, что у меня сейчас есть для кода, это просто команда yum repolist.

#!/bin/bash -x yum -v repolist all | grep -B2 -A6 "enabled" | sed 's/[[:space:]]//g' , 's/--//g' , 's/name=name=/name=/g'

вывод этой команды выглядит следующим образом:

Repo-id: wazuh_repo
Repo-name: Wazuhrepository
Repo-status: enabled
Repo-revision: 1536348945
Repo-updated: FriSep712:35:512018
Repo-pkgs: 73
Repo-size: 920M
Repo-baseurl: https://packages.wazuh.com/3.x/yum/
Repo-expire: 21,600second(s)(last:WedOct3108:59:002018)

В нем около 8 записей, и названия всегда одинаковы ... Может кто-нибудь объяснить, как мне пять лет, как преобразовать это в json, я прочитал справочную страницу jq, я прочитал о хэшах. кажется, ничего не имеет смысла. Я знаю, что мне нужно иметь «ключ» / «значение», как их обозначить?

Я просто хочу взять вывод и сделать его похожим на симпатичный JSON, это часть более крупного сценария, который я пишу, чтобы помочь держать поверх репозиториев, которые мы используем на работе. Я просто полностью не получаю JSON, хотя.

edit: я бы предпочел не использовать функцию-обёртку и делать / изучать правильный путь

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Вот несколько более здравый вариант ответа @ CharlesDuffy. Поскольку последний дает отличные пояснительные примечания, дальнейшие объяснения здесь не приводятся.

jq -nR '
  [inputs | index(": ") as $ix | {(.[:$ix]): .[$ix+2:]}]
  | add'

Это позволяет избежать использования split в случае, если «значение» содержит «:». Однако может быть еще лучше не предполагать, что пробел следует за первым соответствующим ":".

Обратите также внимание, что здесь используется add вместо reduce, исключительно для компактности и простоты.

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

Для такого рода проблем я бы предпочел использовать регулярное выражение для сопоставления ключей и значений. В противном случае я бы выбрал подход, аналогичный подходу Чарльза.

$ ... | jq -Rn 'reduce (inputs | capture("(?<k>[^:]+):\\s*(?<v>.+)")) as {$k, $v} ({}; .[$k] = $v)'
0 голосов
/ 31 октября 2018

Итак, во-первых, чтобы люди, у которых нет yum, могли это проверить, давайте создадим функцию-обертку:

write_output() { cat <<EOF
Repo-id: wazuh_repo
Repo-name: Wazuhrepository
Repo-status: enabled
Repo-revision: 1536348945
Repo-updated: FriSep712:35:512018
Repo-pkgs: 73
Repo-size: 920M
Repo-baseurl: https://packages.wazuh.com/3.x/yum/
Repo-expire: 21,600second(s)(last:WedOct3108:59:002018)
EOF
}

Примечательно, что все ваши ключи идут перед строкой :, а значения идут после них - поэтому мы хотим читать построчно, разбивать на основе последовательностей в двоеточии, рассматривать то, что было впереди, как и обработайте то, что находится сзади, как значение.


Учитывая, что:

jq -Rn '[inputs | split(": ")] | reduce .[] as $kv ({}; .[$kv[0]] = $kv[1])' < <(write_output)

... правильно выбрасывает:

{
  "Repo-id": "wazuh_repo",
  "Repo-name": "Wazuhrepository",
  "Repo-status": "enabled",
  "Repo-revision": "1536348945",
  "Repo-updated": "FriSep712:35:512018",
  "Repo-pkgs": "73",
  "Repo-size": "920M",
  "Repo-baseurl": "https://packages.wazuh.com/3.x/yum/",
  "Repo-expire": "21,600second(s)(last:WedOct3108:59:002018)"
}

... так, как это работает?

  • jq -R включает необработанный ввод режим; входные данные анализируются как последовательность необработанных строк, а не как последовательность документов JSON.
  • jq -n рассматривает null как единственный прямой ввод, поэтому при необходимости можно использовать примитивы input и inputs внутри скрипта.
  • [ inputs ] читает все ваши строки ввода и помещает их в один массив.
  • [ inputs | split(": ")] изменяет это с массива строк на массив списков - с содержимым как до, так и после последовательности ": ".
  • reduce .[] as $kv ( {}; ... ) запускает редуктор с начальным значением {}, а затем подает каждое значение, которое оценивает .[] (то есть каждый элемент в вашем списке) в это редуктор (код ...) как переменная $kv, заменяя значение . каждый раз.

Чтобы запустить это с вашей командой yum в качестве реального ввода, измените < <(write_output) на < <(yum -v repolist all | grep -B2 -A6 "enabled" | sed 's/[[:space:]]//g' , 's/--//g' , 's/name=name=/name=/g').

...