JQ - Какой тип данных запятого фильтра - PullRequest
2 голосов
/ 01 марта 2020

Вопрос

Каков тип данных фильтра запятой JQ?

Фон

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

$ printf '{"ika":5,"uni":3}' | jq '.ika, .uni | .'
5
3

$ printf '{"ika":5,"uni":3}' | jq '.ika, .uni | . | add'
jq: error (at <stdin>:0): Cannot iterate over number (5)

Чтобы обойти, нужно явно преобразовать в массив.

$ printf '{"ika":5,"uni":3}' | jq '[ .ika, .uni ] | . | add'
8

Уточнения

Согласно руководству по JQ, вывод фильтра JQ будет последовательность пробелов -separated JSON data

Однако выходной фильтр запятая (который указан как один из фильтров Basi c), по-видимому, не равен a последовательность разделенных пробелами JSON данных .

Basi c фильтры

Запятая :, Если два фильтра разделены запятой, то один и тот же вход будет подан в оба, и потоки выходных значений двух фильтров будут объединены в следующем порядке: сначала все выходы, созданные левым выражением, а затем все выходы производится по праву. Например, фильтр .foo, .bar создает поля «foo» и «bar» как отдельные выходы.

JQ Manual

* Фильтры 1043 * jq работают с потоком данных JSON. Входные данные для jq анализируются как последовательность значений JSON, разделенных пробелами, которые пропускаются через предоставленный фильтр по одному за раз. Выходные данные фильтра записываются в стандартный формат, снова как последовательность разделенных пробелами JSON данных . Важно помнить, что каждый фильтр имеет вход и выход. Даже литералы типа «привет» или «42» являются фильтрами - они принимают входные данные, но всегда выдают тот же литерал, что и выходные данные . Операции, объединяющие два фильтра, такие как сложение, обычно подают одинаковые входные данные обоим и объединяют результаты.

Так что же выводит фильтр запятая ? Если это JSON data , как сказано в руководстве JQ? Я полагаю, если это будет JSON, то должен ли это быть массив?

[5, 3]

Обновление

На основании ответов:

В выражениях jq, таких как P | Q, фильтр Q обрабатывает каждый элемент в потоке, создаваемом P по одному. В вызове jq P каждый элемент в потоке STDIN обрабатывается P по одному за раз.

$ printf '{"ika":5,"uni":3}' | \
jq '.ika, .uni' | \
jq '"JQ is processing the \(input_line_number) th line whose input value is \(.)"'

"JQ is processing the 1 th line whose input value is 5"
"JQ is processing the 2 th line whose input value is 3"

enter image description here

Ответы [ 2 ]

3 голосов
/ 01 марта 2020

Выражение запятой в jq принимает форму P, Q и, как и все выражения jq, создает поток значений JSON, в этом случае поток, созданный P, сопровождается потоком, созданным Q.

Здесь «поток» означает последовательность из 0 или более JSON значений, и его не следует путать с массивом JSON значений. «Поток JSON значений» сам по себе не является значением JSON.

Если это неясно, вас может заинтересовать мое «Потоковое введение в jq»

Elaboration

Выражения jq сами по себе не являются "типами данных", но каждое выражение jq является фильтром, который принимает в качестве входных данных поток значений JSON и создает поток значений JSON , Используя обозначение JSON* для обозначения «потока JSON значений», понимая, что поток может быть концептуально неограниченным по длине, мы можем рассматривать выражения jq как отображения от JSON* до JSON *.

Это важно понимать, поскольку все выражения jq всегда следует понимать с точки зрения их входных данных. В случае P,Q важным моментом является то, что если R является выражением jq, то:

R | (P,Q)

эквивалентно:

(R|P), (R|Q)

(Это очень важно во-первых, потому что это делает jq очень мощным - R фактически дублируется, а во-вторых, потому что это сильно отличает поведение jq-канала от внешне схожего поведения shell-труб - рассмотрим, например, P | (Q;R) в .)

Опция командной строки -n указывает, что null следует использовать в качестве начального JSON значения, например:

jq -n 1,2

производит:

1
2

Параметр командной строки -s

Вызов jq формы jq P приводит к тому, что каждый элемент JSON в STDIN будет представлен фильтру jq P на Поодиночке.

В отличие от этого, вызов формы jq -s P заставляет элементы в STDIN оборачиваться в массив JSON, который затем представляется в P.

reduce, foreach, foo(P), et c

jq также поддерживает сокращение по потоку. Это особенно полезно при использовании встроенного фильтра inputs, чтобы обойти необходимость использования параметра командной строки -s для обработки потока внешних входных данных.

Параметризованные фильтры, такие как в форме foo(P), где P - произвольное выражение jq, также поддерживаются.

Подробнее см. Руководство jq, ранее упомянутый документ и / или другую документацию.

1 голос
/ 01 марта 2020

Каков тип данных фильтра запятой JQ?

В действительности нет такого понятия, как тип данных , возвращаемый фильтром запятой ...

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

Возможно, хороший способ понять, что он видит этот результат:

$ printf '{"ika":[4,9],"uni":[1,3,5]}' | jq '.ika, .uni | add'
13
9

Два массива прошел через фильтр «добавить», но каждый сам по себе, и два результата сообщили в конце.

Перечитайте документы для запятой, вы увидите, что это говорит:

Если два фильтра разделены запятой, то один и тот же вход будет подан в оба , а в два выходных фильтра потоки значений будут объединены по порядку: сначала все выходы производятся левым выражением, а затем все выходы производятся правым.

Вы можете превратить их в массив , но вы должны сделать это явно. Например:

$ printf '{"ika":[4,9],"uni":[1,3,5]}' | jq '[ .ika, .uni | add ]'
[
  13,
  9
]
...