jq map_values ​​для очень большого файла - PullRequest
0 голосов
/ 03 мая 2019

Я использую jq для поиска шаблонов в очень большом файле JSON (500 МБ +) со следующей структурой плоских объектов:

{
   "prop1": "large string",
   "prop2": "another large string",
   "prop3": "yet another large string",
   ...
}

Приведенный ниже запрос работает нормально, и для возврата результатов требуется менее 15 секунд:

jq 'map(select(contains("PATTERN")==true))' largefile.json > res.json

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

jq 'map_values(select(contains("PATTERN")==true))' largefile.json > res.json

, запрос выполняется вечно.

Существует ли эквивалентный запрос, быстрый по типу map,и который также может предоставить мне пары ключ: значение?

Ответы [ 3 ]

1 голос
/ 03 мая 2019

Поскольку ваш файл JSON не слишком велик для чтения jq, простым и эффективным решением (по модулю использования jq для чтения файла в память) было бы использование keys_unsorted/0 и test/1:

keys_unsorted[] as $k
| select(.[$k] | test("another"))
| [$k, .[$k]]

(Использование map_values было бы излишне неэффективным, и использование contains, вероятно, не является хорошей идеей, если вы полностью не понимаете его сложности.)

Если вы хотите, чтобы вывод былотдельный объект, вы можете либо адаптировать выше, или (за счет памяти, необходимой для выходного объекта):

. as $in
| reduce keys_unsorted[] as $k ({};
    if ($in[$k] | test("another"))
    then  .[$k] = $in[$k]
    else . end)

очень большие файлы

для файлов, которые слишком велики длячитать в jq нормально, вы можете использовать потоковый парсер jq, то есть использовать опцию командной строки --stream.К сожалению, это легче сказать, чем сделать, но простым подходом было бы использовать atomize, как определено, например, в jq --stream filter для нескольких значений одного и того же ключа

0 голосов
/ 04 мая 2019

Просто используйте with_entries/1, что позволяет эффективно отфильтровывать свойства объекта по ключу и / или значению.

with_entries(select(.value | contains("PATTERN")))
0 голосов
/ 03 мая 2019

позвольте мне предложить альтернативное решение по вашему запросу - Unix-инструмент Walk-Path для JSON: jtcjtc вы «кодируете» свой запрос в сам путь обхода, поэтому ваш запрос будет выглядеть следующим образом:

bash $ jtc -w'<\banother\b>R:' -l largefile.json
"prop2": "another large string"
"prop3": "yet another large string"
bash $ 

, где значение в <...>R на самом деле является шаблоном RE (то есть \banother\bв примере).И если вы хотите обернуть полученные элементы, которые вы прошли, в массив JSON, добавьте -j option

Раскрытие информации: я создатель jtc tool

...