Печать всех ключей и значений в одну строку после сортировки ключей - PullRequest
0 голосов
/ 07 апреля 2020

У меня есть папка с более чем 1000 журналами запросов (сгенерированными в час / день) в следующем формате:

[
  {
    "input": {
      "random_param_name_1": "random_value_1",
      "random_param_name_2": "random_value_2",
      "random_param_name_3": "random_value_3",
      "random_param_name_4": "random_value_4"
    },
    "output": {
      "some_key_we_dont_care_about": "some_value_we_dont_care_about"
    },
    "status_code": 200
  },
  {
    "input": {
      "random_param_name_1": "random_value_1",
      "random_param_name_4": "random_value_4",
      "random_param_name_3": "random_value_3",
      "random_param_name_5": "random_value_5"
    },
    "output": {
      "some_key_we_dont_care_about": "some_value_we_dont_care_about"
    },
    "status_code": 200
  }
]

И мне нужно найти все входные запросы, которые являются уникальными. Для этого мне нужно сделать две вещи:

  1. отсортировать ключи в input, поскольку разные входы могут иметь одинаковые ключи, но в разном порядке
  2. распечатать все ключ и значение в в одну строку, чтобы я мог направить вывод в sort | uniq, чтобы получить все уникальные комбинации ввода.

Обратите внимание, что клавиши ввода являются случайными, большинство существующих вопросов в stackoverflow аналогичного вида Знайте ключи заранее, но здесь дело обстоит не так.

Я могу напечатать ключ и значения следующим образом:

jq -r 'keys[] as $k | "\($k):(.[$k])"' 

но они в конечном итоге окажутся в новых строках.

Подводя итог, для вышеупомянутого json мне нужно magic_expression

$ jq 'magic_expression' log.json

, которое вернет

"random_param_name_1":"random_value_1","random_param_name_2":"random_value_2","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4"
"random_param_name_1":"random_value_1","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4","random_param_name_5":"random_value_5"

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020

Примите во внимание следующее:

/workspaces # jq 'map(.input)' data.json 
[
  {
    "random_param_name_1": "random_value_1",
    "random_param_name_2": "random_value_2",
    "random_param_name_3": "random_value_3",
    "random_param_name_4": "random_value_4"
  },
  {
    "random_param_name_1": "random_value_1",
    "random_param_name_4": "random_value_4",
    "random_param_name_3": "random_value_3",
    "random_param_name_5": "random_value_5"
  }
]

Вы можете отсортировать ключи каждого объекта с помощью --sort-keys:

/workspaces # jq --sort-keys 'map(.input)' data.json 
[
  {
    "random_param_name_1": "random_value_1",
    "random_param_name_2": "random_value_2",
    "random_param_name_3": "random_value_3",
    "random_param_name_4": "random_value_4"
  },
  {
    "random_param_name_1": "random_value_1",
    "random_param_name_3": "random_value_3",
    "random_param_name_4": "random_value_4",
    "random_param_name_5": "random_value_5"
  }
]

Затем передать это в другой фильтр jq:

/workspaces # jq --sort-keys 'map(.input)' data.json | jq -r 'map(to_entries)[] | map("\"\(.key)\":\"\(.value)\"") | join(",")'
"random_param_name_1":"random_value_1","random_param_name_2":"random_value_2","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4"
"random_param_name_1":"random_value_1","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4","random_param_name_5":"random_value_5"
2 голосов
/ 07 апреля 2020

Вот "магическое c выражение", чтобы вы начали.
Он использует to_entries, чтобы сделать объекты, появляющиеся в .input, более управляемыми.

def format: "\"\(.key)\":\"\(.value)\"" ;
map(.input) | unique | map(to_entries)[] | map(format) | join(",")

При запуске с -r / --raw-output он производит

"random_param_name_1":"random_value_1","random_param_name_2":"random_value_2","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4"
"random_param_name_1":"random_value_1","random_param_name_4":"random_value_4","random_param_name_3":"random_value_3","random_param_name_5":"random_value_5"

Попробуйте онлайн!

РЕДАКТИРОВАТЬ: если как customcommander указывает, что вы хотите отсортировать ключи, вы можете переместить format до unique. например,

def format: "\"\(.key)\":\"\(.value)\"" ;
map(.input | to_entries | map(format) | sort ) | unique[] | join(",")

, который выдает

"random_param_name_1":"random_value_1","random_param_name_2":"random_value_2","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4"
"random_param_name_1":"random_value_1","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4","random_param_name_5":"random_value_5"

при работе с -r / --raw-output

Попробуйте онлайн!

1 голос
/ 07 апреля 2020

Мне нужно найти все входные запросы, которые являются уникальными.

Это можно сделать в jq без какой-либо сортировки ключей, поскольку оператор jq's == игнорирует порядок ключей. Например, следующее будет выдавать уникальные запросы ввода в их исходной форме (то есть без сортировки ключей):

map(.input)
| group_by(.)
| map(.[0])

Поскольку group_by использует ==, уникальность гарантируется.

Если вы действительно хотите, чтобы ключи были отсортированы, то вы можете использовать параметр командной строки -S:

jq -S -f program.jq input. json

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

map(.input)
| group_by(.)
| map(.[0])
| .[]
| . as $in
| [ keys[] as $k | "\"\($k)\":\"\($in[$k])\"" ] | join(",")

С вашим вводом сэмпла, последний выдает:

"random_param_name_1":"random_value_1","random_param_name_2":"random_value_2","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4"
"random_param_name_1":"random_value_1","random_param_name_3":"random_value_3","random_param_name_4":"random_value_4","random_param_name_5":"random_value_5"
...