LINUX.ORG.RU

Альтернатива jq

 


1

2

Меня его ублюдский марсианский синтакис бесит. Я очень хорошо знаю JavaScript, но на этом дерьмище не могу даже простой фильтр сделать типа [].filter(a => 'somekey' in a.data). И мануал для этой хрени ужасен. Не понимаю людей, которые изобретают какоие-то говноязыки с говносинтаксисом

★★

Последнее исправление: tz4678 (всего исправлений: 1)

У меня тоже такое было, оказалось, я просто невнимательно четал мануал, особенно в самом начале, где описывается принцип работы.

Nervous ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Чот подумал, а вдруг тебе действительно нужен был фильтр как в примере, и я по сути не ответил:

  • [i for i in [{...}, ...] if "bar" in i]
  • list(filter(lambda i: "bar" in i, [{...}, ...]))
WitcherGeralt ★★
()

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

TDrive_2
()

Такое нашел https://github.com/antonmedv/fx/blob/master/DOCS.md

Не пойму как это дерьмище заставить JSONL фильтровать…

cat output/alexa.json | head -10 | fx 'a => a.headers.server === "Apache"' 

false
false
false
false
true
false
false
false
false
false


$ cat output/alexa.json | head -10 | fx '.headers.server === "Apache" && {...this}' 

false
false
false
false
{
  "title": null,
  "url": "http://baidu.com/",
  "meta_generator": null,
  "headers": {
    "content-length": "81",
    "accept-ranges": "bytes",
...
tz4678 ★★
() автор топика

простой фильтр сделать типа [].filter(a => 'somekey' in a.data)

echo '[{"id": 1, "name": "Ololosha"}, {"id": 2, "name": "Trololosha", "systemd": true}]' | jq '.[] | select(.systemd == true)'
{
  "id": 2,
  "name": "Trololosha",
  "systemd": true
}

Не?

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 2)
Ответ на: комментарий от tz4678

Я смог:

cat output/alexa.json | head -10 | fx 'select(x => x.headers.server === "Apache")' 

{
  "title": null,
  "url": "http://baidu.com/",
  "meta_generator": null,
  "headers": {
tz4678 ★★
() автор топика
Ответ на: комментарий от Nervous

Не, спасибо, я все время забываю как что-то сделать на этом jq. Это просто ужас. Он может понравиться только тем, кто не осилил js.

tz4678 ★★
() автор топика
Последнее исправление: tz4678 (всего исправлений: 1)
Ответ на: комментарий от tz4678

все время забываю, как что-то сделать

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

Более кошерный вариант, выдает отфильтрованный список (валидный JSON), а не кучу последовательных объектов:

echo '[{"id": 1, "name": "Ololosha"}, {"id": 2, "name": "Trololosha", "systemd": true}]' | jq 'map(select(.systemd == true))'
[
  {
    "id": 2,
    "name": "Trololosha",
    "systemd": true
  }
]

Стековерфлоу стронк! %)

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от wandrien

Как на крутись, в общем, а какой-то язычок для транформации джейсона учить все равно придется. Лучше, если это будет хотя бы популярный язычок.

Ну или писать скриптики на своем любимом ЯП, если уж совсем аллергия. Что-нибудь вроде

#!/usr/bin/env bb

;; Filters an array of users stored in a JSON file.

(require '[cheshire.core :as json])


(defn systemd-positive?
  "Find out if user is systemd-positive."
  [user]
  (get user "systemd"))


(let [file-name (first *command-line-args*)
      users (-> file-name
                slurp
                json/parse-string)]
  (->> users
       (filter systemd-positive?)
       json/generate-string
       println))
Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от Nervous

Учитывая существование теперь QuickJS, если стоит задача парсить JSON, можно вообще всю логику утилиты сразу написать на нём, без кода на SH и соответственно необходимости запускать JQ.

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

Учитывая существование теперь QuickJS

Удваиваю этого гражданина. Собственно можно и тупо ноду использовать. Нафиг нужны какие-то костыли?

echo '[{"foo": 1, "bar": 2}, {"foo": 3, "bar": 4}]' |node -p 'JSON.parse(fs.readFileSync(process.stdin.fd,"utf-8")).filter(i => i.bar === 2)'

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file
~/work
➜ head -n10 output/alexa.json | fq 'this.headers.server'
Apple
Microsoft-IIS/10.0
ATS/8.0.8
Apache
gws
GitHub.com
gws

~/bin/fq:

#!/usr/bin/env node
const readline = require('readline')
async function run() {
  const rl = readline.createInterface(process.stdin)
  const filters = process.argv.slice(2).map(c => Function('return ' + c))
  for await (line of rl) {
    let rv = JSON.parse(line)
    for (const filter of filters) {
      rv = filter.call(rv)
    }
    if (rv)
      console.log(rv)
  }
}
run()
➜ head -n10 output/alexa.json | fq 'this.headers' 'this.server'
Apple
Microsoft-IIS/10.0
ATS/8.0.8
Apache
gws
GitHub.com
gws

tz4678 ★★
() автор топика
Последнее исправление: tz4678 (всего исправлений: 3)
Ответ на: комментарий от no-such-file

Тайко скрипт нормально обрабатывает огромные JSONL файлы и не выжирает память:

#!/usr/bin/env node
const fs = require('fs')
const readline = require('readline')
async function run() {
  const input = process.argv.length > 3 ? fs.createReadStream(process.argv[2]) : process.stdin
  const expr = process.argv.length > 3 ? process.argv[3] : process.argv[2] 
  const filter = Function('return ' + expr)
  const rl = readline.createInterface({ input })
  for await (line of rl) {
    try {
      const obj = JSON.parse(line)
      const result = filter.call(obj)
      if (result) {
        console.log(obj)
      }
    } catch (e) {
      console.error(e)
    }
  }
}
run()

$ filter-jsonl output/alexa.json 'this.headers.server === "Apache"'

https://gist.github.com/tz4678/499f14bbb0bfe32bbc61d8cec8235021

tz4678 ★★
() автор топика
Последнее исправление: tz4678 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.