С вводом
- groupx:
- groupy:
Выражение yq length
равно 2
С вводом
groupx:
groupy:
Выражение yq length
также равно 2
.[]
) для преобразования случая 1 в вариант 2.Сначала мы преобразуем входные данные случая 1 в случай 2, выполнив:
$ yq '.[]' case1.yaml
groupx:
groupy:
Обратите внимание, что это тот же результат, что и case2.yaml
Если я захочу расширить это выражение выражением case2, я не получу тот же результат, вместо этого я получу следующее:
$ yq '.[] | length' case1.yaml
1
1
Если я добавлю второй процесс yq, я получу тот же результат, что и в случае 2:
$ yq '.[]' case1.yaml | yq 'length'
2
Почему оператор splat yq фактически превращает результат в несколько документов yaml? Это не имеет смысла, поскольку тот же вывод, который снова подается в качестве входных данных в yq, не приводит к созданию нескольких документов.
Если это запланированное поведение, можете ли вы вернуться к одному документу после использования .[]
, не запуская новый процесс yq?
Случай 1 — это один документ с seq (массивом), который содержит две карты (объекты), каждая из которых имеет ровно один ключ (поле).
Случай 2 — один документ с картой (объектом), содержащей два ключа (поля).
Применение .[]
в любом случае деструктурирует тип верхнего уровня документа (seq в первом случае, карту во втором) и приводит (в обоих случаях) к двум документам (первый имеет две карты, второй - две (null) ценности).
Таким образом, применение length
к этому результату в одном и том же фильтре всегда дает два числа (оба 1
в первом случае, поскольку у вас есть две карты, содержащие по одному ключу каждая, и оба 0
во втором, поскольку у вас есть два скалярных значения, которые ничего не содержат). .
Однако применение length
к этому результату в другом фильтре приводит к переоценке входных данных. Теперь, в первом случае, две карты с одним элементом сворачиваются в одну, содержащую два элемента, отсюда и общий результат 2
. Во втором случае скалярные значения не могут быть свернуты дальше, поэтому результаты остаются прежними (два числа, оба 0
).
Я не могу говорить за разработчика, задумано это или нет. Но я могу утверждать, что это отклонение применимо только к mikefarah/yq , а не к kislyuk/yq, который продолжает обрабатывать входные данные как два документа, поскольку активно печатает разделитель документов. (Хотя в mikefarah/yq есть опция --no-doc
(или -N
), позволяющая «не печатать разделители документов», но, похоже, она применяется по умолчанию — проверено с версиями v4.34.2 и v4.40.5).
Если это запланированное поведение, можете ли вы вернуться к одному документу после использования
.[]
, не запуская новый процесс yq?
Конечно. Собрать предметы после деструктуризации в один предмет можно, но его реализация зависит от того, какой тип он должен иметь.
Если вы хотите, чтобы это была последовательность результирующих документов, заключите фильтр в скобки, чтобы собрать в него элементы. Таким образом, .[] | … | length
станет [.[] | …] | length
и должно уступить 2
. На самом деле, вы можете сократить [.[] | …]
, используя map(…)
.
Если вы хотите, чтобы это была карта (так же, как она сворачивается при двух вызовах), вы можете использовать ireduce
для итеративного добавления всех элементов к изначально пустой карте: (.[] | …) as $i ireduce ({}; . + $i) | length
. (Примечание: с помощью kislyuk/yq у вас есть фильтр add
, который может свернуть последовательность карт в одну.)
В этот момент я просто радуюсь, что сломана не моя ментальная модель. Действительно,
map()
кажется более очевидным оператором/функцией для использования. Может быть, в прошлом я поспешно дошел до.[]