Как предотвратить yq удаление комментариев и пустых строк?

Здесь Редактируйте объекты yaml в массиве с помощью yq. Ускорить приведение терминала Терминализатора (запись) Я спросил о том, как редактировать yaml с помощью yq. Я получил лучший ответ. Но по умолчанию yq удаляет комментарии и пустые строки. Как предотвратить это поведение?

input.yml

# Specify a command to be executed
# like `/bin/bash -l`, `ls`, or any other commands
# the default is bash for Linux
# or powershell.exe for Windows
command: fish -l

# Specify the current working directory path
# the default is the current working directory path
cwd: null

# Export additional ENV variables
env:
  recording: true

# Explicitly set the number of columns
# or use `auto` to take the current
# number of columns of your shell
cols: 110

выполнять

yq -y . input.yml

результат

command: fish -l
cwd: null
env:
  recording: true
cols: 110

2 ответа

В некоторых ограниченных случаях вы можете использовать diff/patch вместе с yq.
Например, еслиinput.yml содержит ваш вводимый текст, команды

$ yq -y . input.yml > input.yml.1
$ yq -y .env.recording=false input.yml > input.yml.2
$ diff input.yml.1 input.yml.2 > input.yml.diff
$ patch -o input.yml.new input.yml < input.yml.diff

создает файл input.yml.new с сохраненными комментариями, но запись изменена на false:

# Specify a command to be executed
# like `/bin/bash -l`, `ls`, or any other commands
# the default is bash for Linux
# or powershell.exe for Windows
command: fish -l

# Specify the current working directory path
# the default is the current working directory path
cwd: null

# Export additional ENV variables
env:
  recording: false

# Explicitly set the number of columns
# or use `auto` to take the current
# number of columns of your shell
cols: 110

Это улучшение того , как предотвратить удаление yq комментариев и пустых строк?комментарий.

В моем случае было недостаточно diff -Bа также diff -wBпоскольку он по-прежнему не сохраняет пустые строки и продолжает генерировать всю разницу в файле как один фрагмент вместо множества небольших фрагментов.

Вот пример ввода ( test.yml):

      # This file is automatically generated
#

content-index:

  timestamp: 1970-01-01T00:00:00Z

  entries:

    - dirs:

        - dir: dir-1/dir-2

          files:

            - file: file-1.dat
              md5-hash:
              timestamp: 1970-01-01T00:00:00Z

            - file: file-2.dat
              md5-hash:
              timestamp:

            - file: file-3.dat
              md5-hash:
              timestamp:

        - dir: dir-1/dir-2/dir-3

          files:

            - file: file-1.dat
              md5-hash:
              timestamp:

            - file: file-2.dat
              md5-hash:
              timestamp:

Если попытаться отредактировать поле и создать файл различий:

      diff -B test.yml <(yq -y ".\"content-index\".timestamp=\"2022-01-01T00:00:00Z\"" test.yml)

Он продолжает удалять пустые строки:

      5,7c2
<
<   timestamp: 1970-01-01T00:00:00Z
<
---
>   timestamp: '2022-01-01T00:00:00Z'

Добавляет везде nullвместо пустого поля и изменяет остальные поля меток времени (что означает, что вы должны использовать '...', чтобы сохранить их как есть):

      17,19c8,9
<               md5-hash:
<               timestamp: 1970-01-01T00:00:00Z
<
---
>               md5-hash: null
>               timestamp: '1970-01-01T00:00:00+00:00'

В -wBflags изменяет файл различий с одного фрагмента на несколько фрагментов, но по-прежнему удаляет пустые строки.

Вот упоминание об этой проблеме с разницей: https://unix.stackexchange.com/questions/423186/diff-how-to-ignore-empty-lines/423188#423188

Чтобы исправить это, вы должны использовать его с grep:

      diff -wB <(grep -vE '^\s*$' test.yml) <(yq -y ".\"content-index\".timestamp=\"2022-01-01T00:00:00Z\"" test.yml)

Но, тем не менее, он по-прежнему удаляет комментарии:

      1,2d0
< # This file is automatically generated
< #

Вот решение для этого: https://unix.stackexchange.com/questions/17040/how-to-diff-files-ignoring-comments-lines-starting-with/17044#17044

Итак, полный лайнер:

      diff -wB <(grep -vE '^\s*(#|$)' test.yml) <(yq -y ".\"content-index\".timestamp=\"2022-01-01T00:00:00Z\"" test.yml) | patch -o - test.yml 2>/dev/null

Где 2>/dev/nullстоит игнорировать предупреждения патча, такие как:

      Hunk #1 succeeded at 6 (offset 4 lines).

Чтобы избежать этого в реальном коде, вы можете использовать -sфлаг вместо:

      ... | patch -s -o ...

Обновление :

Существует лучшая полная реализация в виде сценария оболочки для составного действия конвейера GitHub Actions.

Составное действие GitHub: https://github.com/andry81-devops/gh-action--accum-content

Баш-скрипты:

https://github.com/andry81-devops/gh-workflow/blob/master/bash/cache/accum-content.sh
https://github.com/andry81-devops/gh-workflow/blob/master/bash/github/init-yq-workflow.sh

Реализация может использовать 2 из yqреализации:

Ищи: yq_edit, yq_diff, yq_patchфункции

Другие вопросы по тегам