Я хотел бы предоставить структурированный файл конфигурации, который как можно проще для нетехнического пользователя редактировать (к сожалению, это должен быть файл), и поэтому я хотел использовать YAML. Я не могу найти какой-либо способ разбора этого из сценария оболочки Unix, однако.
193
yq
для чтения / записи yaml файлов в оболочке. Страница проекта здесь: mikefarah.github.io/yq Вы можете установить инструмент сbrew
,apt
или загрузить бинарный файл. Чтение значения так же просто, какyq r some.yaml key.value
Ответы:
Мой вариант использования может совпадать или не совпадать с тем, о чем просил этот оригинальный пост, но он определенно похож.
Мне нужно включить некоторые YAML в качестве переменных bash. YAML никогда не будет глубиной более одного уровня.
YAML выглядит так:
Вывод как у дис:
Я добился результата с помощью этой строки:
s/:[^:\/\/]/="/g
находит:
и заменяет его="
, игнорируя://
(для URL)s/$/"/g
добавляет"
в конец каждой строкиs/ *=/=/g
удаляет все пробелы перед=
источник
{KEY: 'value', ...}
; и, возможно, другие. Самое главное, если вы намереваетесь оценить результат в виде шелл-кода, это будет очень небезопасно.Вот синтаксический анализатор только для bash, который использует sed и awk для анализа простых файлов yaml:
Он понимает файлы, такие как:
Который, когда анализируется с использованием:
будет выводить:
он также понимает файлы yaml, сгенерированные ruby, которые могут включать символы ruby, например:
и выдаст то же, что и в предыдущем примере.
Типичное использование в скрипте:
parse_yaml принимает аргумент префикса, чтобы у всех импортированных настроек был общий префикс (что уменьшит риск конфликтов пространства имен).
выходы:
Обратите внимание, что на предыдущие настройки в файле могут ссылаться более поздние настройки:
Еще одно полезное использование - сначала проанализировать файл по умолчанию, а затем пользовательские настройки, которые работают, так как последние переопределяют первые:
источник
-
нотацию yaml в собственные массивы bash!global__debug
вместоglobal_debug
.Я написал
shyaml
на python для запросов YAML из командной строки оболочки.Обзор:
Файл YAML примера (со сложными функциями):
Основной запрос:
Более сложный циклический запрос для сложных значений:
Несколько ключевых моментов:
\0
дополняемый вывод доступен для сплошной многострочной манипуляции.subvalue.maintainer
является действительным ключом).subvalue.things.-1
является последним элементомsubvalue.things
последовательности.)Больше примеров и документации доступно на странице shyaml github или на странице PyyPI shyaml .
источник
cat docker-compose.yml | shyaml get-value api.environment | grep -v null | awk -F': ' '{print $2 > ("envdir/" $1)}'
shyaml
это смехотворно медленно( https://github.com/mikefarah/yq#readme )
В качестве примера (украдено прямо из документации ) приведен файл sample.yaml:
затем
будет выводить
источник
Можно передать небольшой скрипт некоторым интерпретаторам, например Python. Простой способ сделать это с помощью Ruby и его библиотеки YAML заключается в следующем:
где
data
хеш (или массив) со значениями из yaml.В качестве бонуса, это будет хорошо разбирать переднюю тему Джекилла .
источник
RUBY_SCRIPT
Переменная рубиновый скрипт , который может быть записан в файл вместо (бежать сruby -ryaml <rubyscript_filename>
). Он содержит логику для преобразования входного текста в некоторый выходной текст, внутренне сохраняя содержимое вdata
переменную. Echo выводит текст yaml, ноcat <yaml_filename>
вместо этого вы можете использовать для передачи содержимого файла.stdout
передать данные в переменную, вам не нужно полагаться на временные файлы! использоватьx=$(...)
или дажеread a b c < <(...)
). Таким образом, это правильное решение, когда вы точно знаете, что хотите получить в файле YAML, и знаете, как написать строки рубина для доступа к этим данным. Даже если это грубо, это полное доказательство идеи идеи ИМХО. Тем не менее, это правда, что он не предоставляет вам полную абстракцию bash.Учитывая, что Python3 и PyYAML в настоящее время представляют собой довольно простые зависимости, может помочь следующее:
источник
yaml.safe_load
как это безопаснее. pyyaml.org/wiki/PyYAMLDocumentationВот расширенная версия ответа Стефана Фарестама:
Эта версия поддерживает
-
обозначения и краткие обозначения для словарей и списков. Следующий вход:производит этот вывод:
как вы можете видеть,
-
элементы автоматически нумеруются, чтобы получить разные имена переменных для каждого элемента. Вbash
нем нет многомерных массивов, так что это один из способов обхода. Несколько уровней поддерживаются. Чтобы обойти проблему с конечными пробелами, упомянутую @briceburg, нужно заключить значения в одинарные или двойные кавычки. Однако есть некоторые ограничения: расширение словарей и списков может давать неправильные результаты, если значения содержат запятые. Кроме того, более сложные структуры, такие как значения, охватывающие несколько строк (например, ssh-ключи), (пока) не поддерживаются.Несколько слов о коде: первая
sed
команда расширяет краткие формы словарей{ key: value, ...}
до обычных и преобразует их в более простой стиль yaml. Второйsed
вызов делает то же самое для коротких обозначений списков и преобразует[ entry, ... ]
их в подробный список с-
обозначениями. Третийsed
вызов является исходным, который обрабатывает обычные словари, теперь с добавлением для обработки списков с-
отступами.awk
Часть вводит индекс для каждого уровня отступа и увеличивает его , когда имя переменной пусто (т.е. при обработке списка). Текущее значение счетчиков используется вместо пустого vname. При подъеме на один уровень счетчики обнуляются.Изменить: я создал хранилище GitHub для этого.
источник
Трудно сказать, потому что это зависит от того, что вы хотите, чтобы парсер извлек из вашего документа YAML. Для простых случаев, вы можете быть в состоянии использовать
grep
,cut
, иawk
т.д. Для более сложного разбора вам нужно будет использовать полномасштабный разборе библиотеку , такие как Пайтон PyYAML или YAML :: Perl .источник
Я просто написал парсер, который я назвал Yay! ( Yaml не Yamlesque! ), Который анализирует Yamlesque , небольшое подмножество YAML. Итак, если вы ищете 100% совместимый YAML-парсер для Bash, то это не так. Однако, если процитировать OP, если вы хотите, чтобы структурированный файл конфигурации был как можно более легким для нетехнического пользователя для редактирования , подобного YAML, это может представлять интерес.
Он вдохновлен более ранним ответом, но записывает ассоциативные массивы ( да, для этого требуется Bash 4.x ) вместо базовых переменных. Это делается таким образом, что позволяет анализировать данные без предварительного знания ключей, чтобы можно было писать код, управляемый данными.
Помимо элементов массива ключ / значение, каждый массив имеет
keys
массив, содержащий список имен ключей,children
массив, содержащий имена дочерних массивов, иparent
ключ, который ссылается на его родителя.Это является примером Yamlesque:
Вот пример, показывающий, как его использовать:
какие выводы:
А вот и парсер:
В связанном исходном файле есть некоторая документация, и ниже приводится краткое объяснение того, что делает код.
yay_parse
Функция сначала локализуетinput
файл или завершает работу со статусом выхода 1. Затем, она определяет набор данныхprefix
, либо явно заданный или полученный из имени файла.Он записывает действительные
bash
команды в свой стандартный вывод, который, если выполняется, определяет массивы, представляющие содержимое файла входных данных. Первый из них определяет массив верхнего уровня:Обратите внимание, что объявления массива являются ассоциативными (
-A
), что является функцией Bash версии 4. Объявления также являются глобальными (-g
), поэтому они могут выполняться в функции, но быть доступными для глобальной области видимости, такой какyay
хелпер:Исходные данные изначально обрабатываются с помощью
sed
. Он удаляет строки, которые не соответствуют спецификации формата Yamlesque, перед тем как разграничить допустимые поля Yamlesque символом- разделителем файлов ASCII и удалить все двойные кавычки, окружающие поле значения.Эти два выражения похожи; они отличаются только тем, что первый выбирает указанные значения, а второй выбирает не заключенные в кавычки.
Файл Сепаратор (28 / гекс 12 / восьмеричные 034) используются , потому что, как непечатаемый характер, то маловероятно, что во входных данных.
Результат передается по
awk
одной строке за раз. Он использует символ FS для назначения каждого поля переменной:Все строки имеют отступ (возможно, ноль) и ключ, но не у всех есть значение. Он вычисляет уровень отступа для строки, разделяющей длину первого поля, которое содержит начальный пробел, на два. Элементы верхнего уровня без отступа находятся на нулевом уровне отступа.
Далее выясняется, что
prefix
использовать для текущего элемента. Это то, что добавляется к имени ключа для создания имени массива. Существуетroot_prefix
массив верхнего уровня, который определяется как имя набора данных и подчеркивание:parent_key
Ключ на уровне отступа выше уровня отступа текущей строки и представляет собой коллекцию , что текущая строка является частью. Пары ключ / значение коллекции будут храниться в массиве, имя которого определено как объединениеprefix
иparent_key
.Для верхнего уровня (нулевого уровня отступа) префикс набора данных используется в качестве родительского ключа, поэтому у него нет префикса (он установлен в
""
). Все остальные массивы имеют префикс root.Затем текущий ключ вставляется в (awk-internal) массив, содержащий ключи. Этот массив сохраняется в течение всего сеанса awk и поэтому содержит ключи, вставленные предыдущими строками. Ключ вставляется в массив, используя его отступ в качестве индекса массива.
Поскольку этот массив содержит ключи из предыдущих строк, удаляются все ключи с уровнем отступа, меньшим, чем уровень отступа текущей строки:
Это оставляет массив ключей, содержащий цепочку ключей, от корня на уровне отступа 0 до текущей строки. Он удаляет устаревшие ключи, которые остаются, когда предыдущая строка была смещена глубже текущей строки.
В последнем разделе выводятся
bash
команды: строка ввода без значения начинает новый уровень отступа ( коллекция на языке YAML), а строка ввода со значением добавляет ключ к текущей коллекции.Имя коллекции - это конкатенация текущей строки
prefix
иparent_key
.Когда ключ имеет значение, ключ с этим значением присваивается текущей коллекции следующим образом:
Первый оператор выводит команду для присвоения значения элементу ассоциативного массива, названного в честь ключа, а второй выводит команду для добавления ключа в
keys
список разделенных пробелами коллекции :Когда ключ не имеет значения, новая коллекция запускается так:
Первый оператор выводит команду для добавления новой коллекции в
children
список разделенных пробелами текущей коллекции, а второй выводит команду для объявления нового ассоциативного массива для новой коллекции:Все выходные данные
yay_parse
могут быть проанализированы как команды bash с помощью команд basheval
илиsource
встроенных команд.источник
examples
иusr/lib
каталоги, Они связаны в моем ответе на вопрос. Если есть интерес, я мог бы разбить его в своем собственном репо.источник
Другой вариант - преобразовать YAML в JSON, а затем использовать jq для взаимодействия с представлением JSON либо для извлечения из него информации, либо для ее редактирования.
Я написал простой скрипт bash, который содержит этот клей - см. Проект Y2J на GitHub
источник
Если вам нужно одно значение, вы можете использовать инструмент, который преобразует ваш документ YAML в JSON и передает
jq
, например, вyq
.Содержание sample.yaml:
Пример:
источник
Я знаю, что это очень конкретно, но я думаю, что мой ответ может быть полезен для определенных пользователей.
Если у вас есть
node
иnpm
установлены на вашем компьютере, вы можете использоватьjs-yaml
.Первая установка:
тогда в вашем скрипте bash
Также, если вы используете,
jq
вы можете сделать что-то подобноеПотому что
js-yaml
преобразует файл yaml в строковый литерал json. Затем вы можете использовать строку с любым парсером json в вашей системе Unix.источник
Если у вас есть Python 2 и PyYAML, вы можете использовать этот парсер, который я написал, который называется parse_yaml.py . Некоторые из более простых вещей, которые он делает, позволяют вам выбрать префикс (в случае, если у вас более одного файла с одинаковыми переменными) и выбрать одно значение из файла yaml.
Например, если у вас есть эти файлы yaml:
staging.yaml:
prod.yaml:
Вы можете загрузить оба без конфликта.
И даже вишня выбирает нужные вам ценности.
источник
Вы могли бы использовать эквивалент в YQ , что написано в golang:
возвращает:
источник
Вы также можете рассмотреть возможность использования Grunt (JavaScript Task Runner). Может быть легко интегрирован с оболочкой. Он поддерживает чтение файлов YAML (
grunt.file.readYAML
) и JSON (grunt.file.readJSON
).Это может быть достигнуто путем создания задачи в
Gruntfile.js
(илиGruntfile.coffee
), например:затем из оболочки просто запустите
grunt foo
(проверьтеgrunt --help
наличие доступных задач).Более того, вы можете реализовать
exec:foo
tasks (grunt-exec
) с входными переменными, передаваемыми из task (foo: { cmd: 'echo bar <%= foo %>' }
), чтобы напечатать вывод в любом формате, который вам нужен, а затем передать его в другую команду.Существует также инструмент, похожий на Grunt, он называется gulp с дополнительным плагином gulp-yaml .
Установить через:
npm install --save-dev gulp-yaml
Пример использования:
Чтобы узнать больше о формате YAML , посетите сайт YAML, чтобы найти доступные проекты, библиотеки и другие ресурсы, которые помогут вам разобрать этот формат.
Другие инструменты:
Jshon
источник
Я знаю, что мой ответ конкретный, но если на одном уже установлены PHP и Symfony , может быть очень удобно использовать YAML-парсер Symfony.
Например:
Здесь я просто использовал
var_dump
для вывода анализируемый массив, но, конечно, вы можете сделать гораздо больше ... :)источник